Merge branch 'dev'
Conflicts: MediaBrowser.Controller/Entities/BaseItem.cs MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/.bower.json MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/.bower.json MediaBrowser.WebDashboard/dashboard-ui/bower_components/iron-icons/.bower.json MediaBrowser.WebDashboard/dashboard-ui/bower_components/iron-icons/bower.json MediaBrowser.WebDashboard/dashboard-ui/strings/html/kk.json MediaBrowser.WebDashboard/dashboard-ui/strings/html/ru.json MediaBrowser.WebDashboard/dashboard-ui/strings/javascript/kk.json MediaBrowser.WebDashboard/dashboard-ui/strings/javascript/ru.json SharedVersion.cs
This commit is contained in:
commit
8a2e023e28
|
@ -37,7 +37,7 @@
|
|||
</Reference>
|
||||
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll</HintPath>
|
||||
<HintPath>..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||
|
|
|
@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick
|
|||
|
||||
private void LogVersion()
|
||||
{
|
||||
_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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="ImageMagickSharp" version="1.0.0.16" targetFramework="net45" />
|
||||
<package id="ImageMagickSharp" version="1.0.0.17" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
</packages>
|
|
@ -198,50 +198,6 @@ namespace MediaBrowser.Api
|
|||
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
|
||||
}
|
||||
|
||||
protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem,bool> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deslugs an artist name by finding the correct entry in the library
|
||||
/// </summary>
|
||||
|
|
|
@ -102,12 +102,16 @@ namespace MediaBrowser.Api
|
|||
/// <returns>System.Object.</returns>
|
||||
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<GameSystem>()
|
||||
.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<Game>();
|
||||
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<Game>()
|
||||
.ToList();
|
||||
|
||||
var lookup = games
|
||||
.ToLookup(i => i.PlayersSupported ?? -1)
|
||||
|
|
|
@ -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<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> 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);
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -63,9 +66,6 @@
|
|||
<Reference Include="ServiceStack.Text">
|
||||
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
|
|
|
@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
|
|||
public async Task<object> Get(GetSimilarMovies request)
|
||||
{
|
||||
var result = await GetSimilarItemsResult(
|
||||
// Strip out secondary versions
|
||||
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
||||
|
||||
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||
|
||||
return ToOptimizedSerializedResultUsingCache(result);
|
||||
}
|
||||
|
@ -128,10 +125,7 @@ namespace MediaBrowser.Api.Movies
|
|||
public async Task<object> Get(GetSimilarTrailers request)
|
||||
{
|
||||
var result = await GetSimilarItemsResult(
|
||||
// Strip out secondary versions
|
||||
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
||||
|
||||
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||
|
||||
return ToOptimizedSerializedResultUsingCache(result);
|
||||
}
|
||||
|
@ -140,8 +134,12 @@ namespace MediaBrowser.Api.Movies
|
|||
{
|
||||
var user = _userManager.GetUserById(request.UserId);
|
||||
|
||||
IEnumerable<BaseItem> movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Movie);
|
||||
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||
};
|
||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
||||
var movies = _libraryManager.GetItems(query, parentIds);
|
||||
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
||||
|
||||
var listEligibleForCategories = new List<BaseItem>();
|
||||
|
@ -184,21 +182,27 @@ namespace MediaBrowser.Api.Movies
|
|||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
||||
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
||||
{
|
||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||
|
||||
var item = string.IsNullOrEmpty(request.Id) ?
|
||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||
|
||||
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
|
||||
|
||||
var inputItems = user == null
|
||||
? _libraryManager.RootFolder.GetRecursiveChildren(filter)
|
||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
||||
|
||||
var list = inputItems.ToList();
|
||||
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||
};
|
||||
var parentIds = new string[] { };
|
||||
var list = _libraryManager.GetItems(query, parentIds)
|
||||
.Where(i =>
|
||||
{
|
||||
// Strip out secondary versions
|
||||
var v = i as Video;
|
||||
return v != null && !v.PrimaryVersionId.HasValue;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
|
||||
{
|
||||
|
@ -379,9 +383,10 @@ namespace MediaBrowser.Api.Movies
|
|||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
|
||||
{
|
||||
Person = name
|
||||
|
||||
});
|
||||
|
||||
var items = allMovies
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace MediaBrowser.Api
|
|||
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
|
||||
}
|
||||
|
||||
Task.Run(() => _installationManager.InstallPackage(package, new Progress<double>(), CancellationToken.None));
|
||||
Task.Run(() => _installationManager.InstallPackage(package, true, new Progress<double>(), CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1562,6 +1562,13 @@ namespace MediaBrowser.Api.Playback
|
|||
RequestedUrl = url
|
||||
};
|
||||
|
||||
//if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||
// (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||
// (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
//{
|
||||
// state.SegmentLength = 6;
|
||||
//}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
|
||||
{
|
||||
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||
|
|
|
@ -111,7 +111,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
throw;
|
||||
}
|
||||
|
||||
await WaitForMinimumSegmentCount(playlist, 3, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
|
||||
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -283,7 +283,7 @@ namespace MediaBrowser.Api
|
|||
private T GetParentWithImage<T>(BaseItem item, ImageType type)
|
||||
where T : BaseItem
|
||||
{
|
||||
return item.Parents.OfType<T>().FirstOrDefault(i => i.HasImage(type));
|
||||
return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,11 +68,7 @@ namespace MediaBrowser.Api
|
|||
_config.Configuration.EnableLocalizedGuids = true;
|
||||
_config.Configuration.MergeMetadataAndImagesByName = true;
|
||||
_config.Configuration.EnableStandaloneMetadata = true;
|
||||
_config.Configuration.EnableLibraryMetadataSubFolder = true;
|
||||
_config.Configuration.EnableCustomPathSubFolders = true;
|
||||
_config.Configuration.DisableXmlSavers = true;
|
||||
_config.Configuration.DisableStartupScan = true;
|
||||
_config.Configuration.EnableUserViews = true;
|
||||
_config.Configuration.EnableDateLastRefresh = true;
|
||||
_config.SaveConfiguration();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommonIO;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace MediaBrowser.Api.System
|
||||
{
|
||||
|
@ -32,6 +33,12 @@ namespace MediaBrowser.Api.System
|
|||
|
||||
}
|
||||
|
||||
[Route("/System/Ping", "POST")]
|
||||
public class PingSystem : IReturnVoid
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class RestartApplication
|
||||
/// </summary>
|
||||
|
@ -59,7 +66,7 @@ namespace MediaBrowser.Api.System
|
|||
|
||||
[Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
|
||||
[Authenticated]
|
||||
public class GetEndpointInfo : IReturn<EndpointInfo>
|
||||
public class GetEndpointInfo : IReturn<EndPointInfo>
|
||||
{
|
||||
public string Endpoint { get; set; }
|
||||
}
|
||||
|
@ -104,6 +111,11 @@ namespace MediaBrowser.Api.System
|
|||
_security = security;
|
||||
}
|
||||
|
||||
public object Post(PingSystem request)
|
||||
{
|
||||
return _appHost.Name;
|
||||
}
|
||||
|
||||
public object Get(GetServerLogs request)
|
||||
{
|
||||
List<FileSystemMetadata> files;
|
||||
|
@ -199,17 +211,11 @@ namespace MediaBrowser.Api.System
|
|||
|
||||
public object Get(GetEndpointInfo request)
|
||||
{
|
||||
return ToOptimizedResult(new EndpointInfo
|
||||
return ToOptimizedResult(new EndPointInfo
|
||||
{
|
||||
IsLocal = Request.IsLocal,
|
||||
IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class EndpointInfo
|
||||
{
|
||||
public bool IsLocal { get; set; }
|
||||
public bool IsInNetwork { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
[ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string StartItemId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Skips over a given number of items within the results. Use for paging.
|
||||
/// </summary>
|
||||
|
@ -273,29 +273,28 @@ namespace MediaBrowser.Api
|
|||
{
|
||||
var user = _userManager.GetUserById(request.UserId);
|
||||
|
||||
var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode);
|
||||
|
||||
var itemsList = _libraryManager
|
||||
.Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending)
|
||||
.Cast<Episode>()
|
||||
.ToList();
|
||||
|
||||
var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList();
|
||||
|
||||
var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime();
|
||||
var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList();
|
||||
|
||||
previousEpisodes.AddRange(unairedEpisodes);
|
||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
||||
|
||||
var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit);
|
||||
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
|
||||
SortOrder = SortOrder.Ascending,
|
||||
MinPremiereDate = minPremiereDate,
|
||||
StartIndex = request.StartIndex,
|
||||
Limit = request.Limit
|
||||
|
||||
}, parentIds);
|
||||
|
||||
var options = GetDtoOptions(request);
|
||||
|
||||
var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray();
|
||||
var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
|
||||
|
||||
var result = new ItemsResult
|
||||
{
|
||||
TotalRecordCount = itemsList.Count,
|
||||
TotalRecordCount = itemsResult.TotalRecordCount,
|
||||
Items = returnItems
|
||||
};
|
||||
|
||||
|
@ -440,7 +439,7 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
|
||||
episodes = season.GetEpisodes(user);
|
||||
}
|
||||
}
|
||||
else if (request.Season.HasValue)
|
||||
{
|
||||
var series = _libraryManager.GetItemById(request.Id) as Series;
|
||||
|
@ -495,7 +494,7 @@ namespace MediaBrowser.Api
|
|||
.ToList();
|
||||
|
||||
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
|
||||
|
||||
|
||||
var dtoOptions = GetDtoOptions(request);
|
||||
|
||||
var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user)
|
||||
|
|
|
@ -206,6 +206,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||
public string Genres { get; set; }
|
||||
|
||||
public string GenreIds { get; set; }
|
||||
|
||||
[ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||
public string OfficialRatings { get; set; }
|
||||
|
||||
|
@ -385,6 +387,11 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public string[] GetGenreIds()
|
||||
{
|
||||
return (GenreIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public string[] GetPersonTypes()
|
||||
{
|
||||
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
|
|
@ -112,6 +112,11 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
||||
parentItem;
|
||||
|
||||
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
|
||||
}
|
||||
|
||||
// Default list type = children
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Ids))
|
||||
|
@ -211,6 +216,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
Tags = request.GetTags(),
|
||||
OfficialRatings = request.GetOfficialRatings(),
|
||||
Genres = request.GetGenres(),
|
||||
GenreIds = request.GetGenreIds(),
|
||||
Studios = request.GetStudios(),
|
||||
StudioIds = request.GetStudioIds(),
|
||||
Person = request.Person,
|
||||
|
@ -423,15 +429,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return false;
|
||||
}
|
||||
|
||||
// Min index number
|
||||
if (request.MinIndexNumber.HasValue)
|
||||
{
|
||||
if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Min official rating
|
||||
if (!string.IsNullOrEmpty(request.MinOfficialRating))
|
||||
{
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
[ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
|
||||
public bool? IncludeExternalContent { get; set; }
|
||||
|
||||
public string PresetViews { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/SpecialViewOptions", "GET")]
|
||||
|
@ -75,9 +77,24 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
query.IncludeExternalContent = request.IncludeExternalContent.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.PresetViews))
|
||||
{
|
||||
query.PresetViews = request.PresetViews.Split(',');
|
||||
}
|
||||
|
||||
var app = AuthorizationContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
|
||||
if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
|
||||
}
|
||||
//query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
|
||||
|
||||
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var dtoOptions = GetDtoOptions(request);
|
||||
dtoOptions.Fields = new List<ItemFields>();
|
||||
dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
|
||||
dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);
|
||||
|
||||
var user = _userManager.GetUserById(request.UserId);
|
||||
|
||||
|
@ -123,7 +140,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
var views = user.RootFolder
|
||||
.GetChildren(user, true)
|
||||
.OfType<Folder>()
|
||||
.Where(i => !UserView.IsExcludedFromGrouping(i))
|
||||
.Where(UserView.IsEligibleForGrouping)
|
||||
.ToList();
|
||||
|
||||
var list = views
|
||||
|
@ -141,9 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
private bool IsEligibleForSpecialView(ICollectionFolder view)
|
||||
{
|
||||
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
|
||||
|
||||
return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
return UserView.IsEligibleForEnhancedView(view.CollectionType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.1.1" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
</packages>
|
|
@ -133,7 +133,7 @@ namespace MediaBrowser.Common.Implementations
|
|||
/// Gets the HTTP client.
|
||||
/// </summary>
|
||||
/// <value>The HTTP client.</value>
|
||||
protected IHttpClient HttpClient { get; private set; }
|
||||
public IHttpClient HttpClient { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the network manager.
|
||||
/// </summary>
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
|
||||
request.Method = method;
|
||||
request.Timeout = options.TimeoutMs;
|
||||
|
||||
|
||||
if (httpWebRequest != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(options.Host))
|
||||
|
|
|
@ -51,9 +51,11 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.4.1.1\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog">
|
||||
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||
|
@ -62,13 +64,14 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=2.8.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SimpleInjector.3.0.5\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Reference Include="SimpleInjector">
|
||||
<HintPath>..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="ServiceStack.Text">
|
||||
|
@ -105,6 +108,7 @@
|
|||
<Compile Include="Security\SuppporterInfoResponse.cs" />
|
||||
<Compile Include="Serialization\JsonSerializer.cs" />
|
||||
<Compile Include="Serialization\XmlSerializer.cs" />
|
||||
<Compile Include="Updates\GithubUpdater.cs" />
|
||||
<Compile Include="Updates\InstallationManager.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Net;
|
|||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using MoreLinq;
|
||||
|
||||
namespace MediaBrowser.Common.Implementations.Networking
|
||||
{
|
||||
|
@ -31,14 +32,14 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
}
|
||||
}
|
||||
|
||||
private volatile List<string> _localIpAddresses;
|
||||
private volatile List<IPAddress> _localIpAddresses;
|
||||
private readonly object _localIpAddressSyncLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the machine's local ip address
|
||||
/// </summary>
|
||||
/// <returns>IPAddress.</returns>
|
||||
public IEnumerable<string> GetLocalIpAddresses()
|
||||
public IEnumerable<IPAddress> GetLocalIpAddresses()
|
||||
{
|
||||
if (_localIpAddresses == null)
|
||||
{
|
||||
|
@ -58,25 +59,24 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
return _localIpAddresses;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetLocalIpAddressesInternal()
|
||||
private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
|
||||
{
|
||||
var list = GetIPsDefault()
|
||||
.Where(i => !IPAddress.IsLoopback(i))
|
||||
.Select(i => i.ToString())
|
||||
.Where(FilterIpAddress)
|
||||
.ToList();
|
||||
|
||||
if (list.Count > 0)
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return list;
|
||||
list.AddRange(GetLocalIpAddressesFallback());
|
||||
}
|
||||
|
||||
return GetLocalIpAddressesFallback().Where(FilterIpAddress);
|
||||
return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
|
||||
}
|
||||
|
||||
private bool FilterIpAddress(string address)
|
||||
private bool FilterIpAddress(IPAddress address)
|
||||
{
|
||||
if (address.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
|
||||
var addressString = address.ToString ();
|
||||
|
||||
if (addressString.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -84,8 +84,16 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool IsInPrivateAddressSpace(string endpoint)
|
||||
public bool IsInPrivateAddressSpace(string endpoint)
|
||||
{
|
||||
if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle ipv4 mapped to ipv6
|
||||
endpoint = endpoint.Replace("::ffff:", string.Empty);
|
||||
|
||||
// Private address space:
|
||||
// http://en.wikipedia.org/wiki/Private_network
|
||||
|
||||
|
@ -96,9 +104,6 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
|
||||
return
|
||||
|
||||
// If url was requested with computer name, we may see this
|
||||
endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||
|
||||
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
|
||||
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
|
||||
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
|
||||
|
@ -131,26 +136,41 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
throw new ArgumentNullException("endpoint");
|
||||
}
|
||||
|
||||
if (IsInPrivateAddressSpace(endpoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const int lengthMatch = 4;
|
||||
|
||||
if (endpoint.Length >= lengthMatch)
|
||||
{
|
||||
var prefix = endpoint.Substring(0, lengthMatch);
|
||||
|
||||
if (GetLocalIpAddresses()
|
||||
.Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress address;
|
||||
if (resolveHost && !IPAddress.TryParse(endpoint, out address))
|
||||
if (IPAddress.TryParse(endpoint, out address))
|
||||
{
|
||||
var addressString = address.ToString();
|
||||
|
||||
int lengthMatch = 100;
|
||||
if (address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
lengthMatch = 4;
|
||||
if (IsInPrivateAddressSpace(addressString))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
lengthMatch = 10;
|
||||
if (IsInPrivateAddressSpace(endpoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be even be doing this with ipv6?
|
||||
if (addressString.Length >= lengthMatch)
|
||||
{
|
||||
var prefix = addressString.Substring(0, lengthMatch);
|
||||
|
||||
if (GetLocalIpAddresses().Any(i => i.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resolveHost)
|
||||
{
|
||||
Uri uri;
|
||||
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
|
||||
|
@ -188,33 +208,45 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||
return Dns.GetHostAddresses(hostName);
|
||||
}
|
||||
|
||||
private IEnumerable<IPAddress> GetIPsDefault()
|
||||
{
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
var props = adapter.GetIPProperties();
|
||||
var gateways = from ga in props.GatewayAddresses
|
||||
where !ga.Address.Equals(IPAddress.Any)
|
||||
select true;
|
||||
private List<IPAddress> GetIPsDefault()
|
||||
{
|
||||
NetworkInterface[] interfaces;
|
||||
|
||||
if (!gateways.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
|
||||
return new List<IPAddress>();
|
||||
}
|
||||
|
||||
foreach (var uni in props.UnicastAddresses)
|
||||
{
|
||||
var address = uni.Address;
|
||||
if (address.AddressFamily != AddressFamily.InterNetwork)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
yield return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return interfaces.SelectMany(network => {
|
||||
|
||||
private IEnumerable<string> GetLocalIpAddressesFallback()
|
||||
try
|
||||
{
|
||||
Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
|
||||
|
||||
var properties = network.GetIPProperties();
|
||||
|
||||
return properties.UnicastAddresses
|
||||
.Where(i => i.IsDnsEligible)
|
||||
.Select(i => i.Address)
|
||||
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error querying network interface", ex);
|
||||
return new List<IPAddress>();
|
||||
}
|
||||
|
||||
}).DistinctBy(i => i.ToString())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<IPAddress> GetLocalIpAddressesFallback()
|
||||
{
|
||||
var host = Dns.GetHostEntry(Dns.GetHostName());
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
212
MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
Normal file
212
MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
Normal file
|
@ -0,0 +1,212 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Common.Implementations.Updates
|
||||
{
|
||||
public class GithubUpdater
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private TimeSpan _cacheLength;
|
||||
|
||||
public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer, TimeSpan cacheLength)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_cacheLength = cacheLength;
|
||||
}
|
||||
|
||||
public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, CancellationToken cancellationToken)
|
||||
{
|
||||
var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
|
||||
|
||||
var options = new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
EnableKeepAlive = false,
|
||||
CancellationToken = cancellationToken,
|
||||
UserAgent = "Emby/3.0"
|
||||
|
||||
};
|
||||
|
||||
if (_cacheLength.Ticks > 0)
|
||||
{
|
||||
options.CacheMode = CacheMode.Unconditional;
|
||||
options.CacheLength = _cacheLength;
|
||||
}
|
||||
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
{
|
||||
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||
|
||||
return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
|
||||
}
|
||||
}
|
||||
|
||||
private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
|
||||
{
|
||||
if (updateLevel == PackageVersionClass.Release)
|
||||
{
|
||||
obj = obj.Where(i => !i.prerelease).ToArray();
|
||||
}
|
||||
else if (updateLevel == PackageVersionClass.Beta)
|
||||
{
|
||||
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
else if (updateLevel == PackageVersionClass.Dev)
|
||||
{
|
||||
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
|
||||
var availableUpdate = obj
|
||||
.Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename))
|
||||
.Where(i => i != null)
|
||||
.OrderByDescending(i => Version.Parse(i.AvailableVersion))
|
||||
.FirstOrDefault();
|
||||
|
||||
return availableUpdate ?? new CheckForUpdateResult
|
||||
{
|
||||
IsUpdateAvailable = false
|
||||
};
|
||||
}
|
||||
|
||||
private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)
|
||||
{
|
||||
Version version;
|
||||
if (!Version.TryParse(obj.tag_name, out version))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (version < minVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename));
|
||||
|
||||
if (asset == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CheckForUpdateResult
|
||||
{
|
||||
AvailableVersion = version.ToString(),
|
||||
IsUpdateAvailable = version > minVersion,
|
||||
Package = new PackageVersionInfo
|
||||
{
|
||||
classification = obj.prerelease ?
|
||||
(obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :
|
||||
PackageVersionClass.Release,
|
||||
name = packageName,
|
||||
sourceUrl = asset.browser_download_url,
|
||||
targetFilename = targetFilename,
|
||||
versionStr = version.ToString(),
|
||||
requiredVersionStr = "1.0.0",
|
||||
description = obj.body
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsAsset(Asset asset, string assetFilename)
|
||||
{
|
||||
var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;
|
||||
|
||||
if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public class Uploader
|
||||
{
|
||||
public string login { get; set; }
|
||||
public int id { get; set; }
|
||||
public string avatar_url { get; set; }
|
||||
public string gravatar_id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public string followers_url { get; set; }
|
||||
public string following_url { get; set; }
|
||||
public string gists_url { get; set; }
|
||||
public string starred_url { get; set; }
|
||||
public string subscriptions_url { get; set; }
|
||||
public string organizations_url { get; set; }
|
||||
public string repos_url { get; set; }
|
||||
public string events_url { get; set; }
|
||||
public string received_events_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public bool site_admin { get; set; }
|
||||
}
|
||||
|
||||
public class Asset
|
||||
{
|
||||
public string url { get; set; }
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public object label { get; set; }
|
||||
public Uploader uploader { get; set; }
|
||||
public string content_type { get; set; }
|
||||
public string state { get; set; }
|
||||
public int size { get; set; }
|
||||
public int download_count { get; set; }
|
||||
public string created_at { get; set; }
|
||||
public string updated_at { get; set; }
|
||||
public string browser_download_url { get; set; }
|
||||
}
|
||||
|
||||
public class Author
|
||||
{
|
||||
public string login { get; set; }
|
||||
public int id { get; set; }
|
||||
public string avatar_url { get; set; }
|
||||
public string gravatar_id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public string followers_url { get; set; }
|
||||
public string following_url { get; set; }
|
||||
public string gists_url { get; set; }
|
||||
public string starred_url { get; set; }
|
||||
public string subscriptions_url { get; set; }
|
||||
public string organizations_url { get; set; }
|
||||
public string repos_url { get; set; }
|
||||
public string events_url { get; set; }
|
||||
public string received_events_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public bool site_admin { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public string url { get; set; }
|
||||
public string assets_url { get; set; }
|
||||
public string upload_url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public int id { get; set; }
|
||||
public string tag_name { get; set; }
|
||||
public string target_commitish { get; set; }
|
||||
public string name { get; set; }
|
||||
public bool draft { get; set; }
|
||||
public Author author { get; set; }
|
||||
public bool prerelease { get; set; }
|
||||
public string created_at { get; set; }
|
||||
public string published_at { get; set; }
|
||||
public List<Asset> assets { get; set; }
|
||||
public string tarball_url { get; set; }
|
||||
public string zipball_url { get; set; }
|
||||
public string body { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -438,11 +438,12 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||
/// Installs the package.
|
||||
/// </summary>
|
||||
/// <param name="package">The package.</param>
|
||||
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">package</exception>
|
||||
public async Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
if (package == null)
|
||||
{
|
||||
|
@ -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.
|
||||
/// </summary>
|
||||
/// <param name="package">The package.</param>
|
||||
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
// Do the install
|
||||
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))
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="NLog" version="4.1.0" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="NLog" version="4.2.3" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.0.5" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.1.2" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MediaBrowser.Common.Net
|
|||
/// Gets the machine's local ip address
|
||||
/// </summary>
|
||||
/// <returns>IPAddress.</returns>
|
||||
IEnumerable<string> GetLocalIpAddresses();
|
||||
IEnumerable<IPAddress> GetLocalIpAddresses();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random port number that is currently available
|
||||
|
@ -25,6 +25,13 @@ namespace MediaBrowser.Common.Net
|
|||
/// <returns>[string] MAC Address</returns>
|
||||
string GetMacAddress();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is in private address space] [the specified endpoint].
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The endpoint.</param>
|
||||
/// <returns><c>true</c> if [is in private address space] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
||||
bool IsInPrivateAddressSpace(string endpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network shares.
|
||||
/// </summary>
|
||||
|
|
|
@ -105,11 +105,12 @@ namespace MediaBrowser.Common.Updates
|
|||
/// Installs the package.
|
||||
/// </summary>
|
||||
/// <param name="package">The package.</param>
|
||||
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">package</exception>
|
||||
Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken);
|
||||
Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Uninstalls a plugin
|
||||
|
|
|
@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
|
|||
|
||||
public List<ChannelMediaInfo> 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()
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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<string> Tags { get; set; }
|
||||
public ExtraType? ExtraType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the artist.
|
||||
/// </summary>
|
||||
/// <value>The artist.</value>
|
||||
public List<string> Artists { get; set; }
|
||||
|
||||
public List<string> AlbumArtists { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album.
|
||||
/// </summary>
|
||||
/// <value>The album.</value>
|
||||
public string Album { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsThemeMedia
|
||||
{
|
||||
|
@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
{
|
||||
Artists = new List<string>();
|
||||
AlbumArtists = new List<string>();
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
locationType != LocationType.Virtual;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the artist.
|
||||
/// </summary>
|
||||
/// <value>The artist.</value>
|
||||
public List<string> Artists { get; set; }
|
||||
|
||||
public List<string> AlbumArtists { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public List<string> AllArtists
|
||||
{
|
||||
|
@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album.
|
||||
/// </summary>
|
||||
/// <value>The album.</value>
|
||||
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()
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
{
|
||||
get
|
||||
{
|
||||
return Parents.OfType<MusicArtist>().FirstOrDefault();
|
||||
return GetParents().OfType<MusicArtist>().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<AlbumInfo>();
|
||||
|
||||
id.AlbumArtists = AlbumArtists;
|
||||
|
||||
var artist = Parents.OfType<MusicArtist>().FirstOrDefault();
|
||||
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
|
||||
|
||||
if (artist != null)
|
||||
{
|
||||
|
|
|
@ -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<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var items = GetRecursiveChildren().ToList();
|
||||
|
|
|
@ -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<string>();
|
||||
Genres = new List<string>();
|
||||
Studios = new List<string>();
|
||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <summary>
|
||||
/// The supported image extensions
|
||||
/// </summary>
|
||||
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" };
|
||||
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
|
||||
|
||||
public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
|
||||
|
||||
|
@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name
|
||||
[IgnoreDataMember]
|
||||
public virtual string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -122,14 +124,23 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Gets or sets the id.
|
||||
/// </summary>
|
||||
/// <value>The id.</value>
|
||||
[IgnoreDataMember]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is hd.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool? IsHD { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the audio.
|
||||
/// </summary>
|
||||
/// <value>The audio.</value>
|
||||
[IgnoreDataMember]
|
||||
public ProgramAudio? Audio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
[IgnoreDataMember]
|
||||
public virtual string Path { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id of the program.
|
||||
/// If this content came from an external service, the id of the content on that service
|
||||
/// </summary>
|
||||
[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.
|
||||
/// </summary>
|
||||
/// <value>The date created.</value>
|
||||
[IgnoreDataMember]
|
||||
public DateTime DateCreated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date modified.
|
||||
/// </summary>
|
||||
/// <value>The date modified.</value>
|
||||
[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.
|
||||
/// </summary>
|
||||
/// <value>The name of the forced sort.</value>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -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<Folder> Parents
|
||||
{
|
||||
get
|
||||
get { return GetParents().OfType<Folder>(); }
|
||||
}
|
||||
|
||||
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<BaseItem> GetParents()
|
||||
{
|
||||
var parent = GetParent();
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
yield return parent;
|
||||
|
||||
parent = parent.GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,19 +558,20 @@ namespace MediaBrowser.Controller.Entities
|
|||
public T FindParent<T>()
|
||||
where T : Folder
|
||||
{
|
||||
return Parents.OfType<T>().FirstOrDefault();
|
||||
return GetParents().OfType<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual BaseItem DisplayParent
|
||||
{
|
||||
get { return Parent; }
|
||||
get { return GetParent(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
||||
/// </summary>
|
||||
/// <value>The premiere date.</value>
|
||||
[IgnoreDataMember]
|
||||
public DateTime? PremiereDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Gets or sets the display type of the media.
|
||||
/// </summary>
|
||||
/// <value>The display type of the media.</value>
|
||||
[IgnoreDataMember]
|
||||
public string DisplayMediaType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the official rating.
|
||||
/// </summary>
|
||||
/// <value>The official rating.</value>
|
||||
[IgnoreDataMember]
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the official rating description.
|
||||
/// </summary>
|
||||
/// <value>The official rating description.</value>
|
||||
[IgnoreDataMember]
|
||||
public string OfficialRatingDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom rating.
|
||||
/// </summary>
|
||||
/// <value>The custom rating.</value>
|
||||
//[IgnoreDataMember]
|
||||
[IgnoreDataMember]
|
||||
public string CustomRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the overview.
|
||||
/// </summary>
|
||||
/// <value>The overview.</value>
|
||||
[IgnoreDataMember]
|
||||
public string Overview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Gets or sets the genres.
|
||||
/// </summary>
|
||||
/// <value>The genres.</value>
|
||||
[IgnoreDataMember]
|
||||
public List<string> Genres { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the home page URL.
|
||||
/// </summary>
|
||||
/// <value>The home page URL.</value>
|
||||
[IgnoreDataMember]
|
||||
public string HomePageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating.
|
||||
/// </summary>
|
||||
/// <value>The community rating.</value>
|
||||
//[IgnoreDataMember]
|
||||
[IgnoreDataMember]
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating vote count.
|
||||
/// </summary>
|
||||
/// <value>The community rating vote count.</value>
|
||||
[IgnoreDataMember]
|
||||
public int? VoteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the run time ticks.
|
||||
/// </summary>
|
||||
/// <value>The run time ticks.</value>
|
||||
[IgnoreDataMember]
|
||||
public long? RunTimeTicks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the production year.
|
||||
/// </summary>
|
||||
/// <value>The production year.</value>
|
||||
[IgnoreDataMember]
|
||||
public int? ProductionYear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// This could be episode number, album track number, etc.
|
||||
/// </summary>
|
||||
/// <value>The index number.</value>
|
||||
//[IgnoreDataMember]
|
||||
[IgnoreDataMember]
|
||||
public int? IndexNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For an episode this could be the season number, or for a song this could be the disc number.
|
||||
/// </summary>
|
||||
/// <value>The parent index number.</value>
|
||||
[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<Audio.Audio>()
|
||||
.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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -751,21 +794,21 @@ namespace MediaBrowser.Controller.Entities
|
|||
return LibraryManager.ResolvePaths(files, directoryService, null)
|
||||
.OfType<Video>()
|
||||
.Select(item =>
|
||||
{
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var dbItem = LibraryManager.GetItemById(item.Id) as Video;
|
||||
|
||||
if (dbItem != null)
|
||||
{
|
||||
item = dbItem;
|
||||
}
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var dbItem = LibraryManager.GetItemById(item.Id) as Video;
|
||||
|
||||
item.ExtraType = ExtraType.ThemeVideo;
|
||||
if (dbItem != null)
|
||||
{
|
||||
item = dbItem;
|
||||
}
|
||||
|
||||
return item;
|
||||
item.ExtraType = ExtraType.ThemeVideo;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
}).OrderBy(i => i.Path).ToList();
|
||||
return item;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
}).OrderBy(i => i.Path).ToList();
|
||||
}
|
||||
|
||||
public Task RefreshMetadata(CancellationToken cancellationToken)
|
||||
|
@ -821,7 +864,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
[IgnoreDataMember]
|
||||
protected virtual bool SupportsOwnedItems
|
||||
{
|
||||
get { return IsFolder || Parent != null; }
|
||||
get { return IsFolder || GetParent() != null; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -846,7 +889,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
var localTrailersChanged = false;
|
||||
|
||||
if (LocationType == LocationType.FileSystem && Parent != null)
|
||||
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
||||
{
|
||||
var hasThemeMedia = this as IHasThemeMedia;
|
||||
if (hasThemeMedia != null)
|
||||
|
@ -1008,7 +1051,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (string.IsNullOrWhiteSpace(lang))
|
||||
{
|
||||
lang = Parents
|
||||
lang = GetParents()
|
||||
.Select(i => i.PreferredMetadataLanguage)
|
||||
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
||||
}
|
||||
|
@ -1038,7 +1081,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (string.IsNullOrWhiteSpace(lang))
|
||||
{
|
||||
lang = Parents
|
||||
lang = GetParents()
|
||||
.Select(i => i.PreferredMetadataCountryCode)
|
||||
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
||||
}
|
||||
|
@ -1119,6 +1162,23 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
public int? GetParentalRatingValue()
|
||||
{
|
||||
var rating = CustomRating;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rating))
|
||||
{
|
||||
rating = OfficialRating;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rating))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return LocalizationManager.GetRatingLevel(rating);
|
||||
}
|
||||
|
||||
public int? GetInheritedParentalRatingValue()
|
||||
{
|
||||
var rating = CustomRatingForComparison;
|
||||
|
||||
|
@ -1156,6 +1216,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
return true;
|
||||
}
|
||||
|
||||
public virtual UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Other;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the block unrated value.
|
||||
/// </summary>
|
||||
|
@ -1174,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
||||
return config.BlockUnratedItems.Contains(GetBlockUnratedType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1206,14 +1271,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Parents.Any(i => !i.IsVisible(user)))
|
||||
if (GetParents().Any(i => !i.IsVisible(user)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkFolders)
|
||||
{
|
||||
var topParent = Parents.LastOrDefault() ?? this;
|
||||
var topParent = GetParents().LastOrDefault() ?? this;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(topParent.Path))
|
||||
{
|
||||
|
@ -1307,15 +1372,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a person to the item
|
||||
/// </summary>
|
||||
/// <param name="person">The person.</param>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public void AddPerson(PersonInfo person)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a studio to the item
|
||||
/// </summary>
|
||||
|
@ -1779,8 +1835,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
ProviderIds = ProviderIds,
|
||||
IndexNumber = IndexNumber,
|
||||
ParentIndexNumber = ParentIndexNumber,
|
||||
Year = ProductionYear,
|
||||
PremiereDate = PremiereDate
|
||||
Year = ProductionYear,
|
||||
PremiereDate = PremiereDate
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1875,5 +1931,54 @@ namespace MediaBrowser.Controller.Entities
|
|||
DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IEnumerable<Guid> GetAncestorIds()
|
||||
{
|
||||
return GetParents().Select(i => i.Id).Concat(LibraryManager.GetCollectionFolders(this).Select(i => i.Id));
|
||||
}
|
||||
|
||||
public BaseItem GetTopParent()
|
||||
{
|
||||
if (IsTopParent)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return GetParents().FirstOrDefault(i => i.IsTopParent);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual bool IsTopParent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var view = this as UserView;
|
||||
if (view != null && string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<Guid> GetIdsForAncestorQuery()
|
||||
{
|
||||
return new[] { Id };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,19 +17,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
public string SeriesName { get; set; }
|
||||
|
||||
public Book()
|
||||
{
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
public override bool CanDownload()
|
||||
{
|
||||
var locationType = LocationType;
|
||||
|
@ -37,9 +26,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
locationType != LocationType.Virtual;
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Book);
|
||||
return UnratedItem.Book;
|
||||
}
|
||||
|
||||
public BookInfo GetLookupInfo()
|
||||
|
@ -48,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (string.IsNullOrEmpty(SeriesName))
|
||||
{
|
||||
info.SeriesName = Parents.Select(i => i.Name).FirstOrDefault();
|
||||
info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -181,9 +181,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
private List<LinkedChild> GetLinkedChildrenInternal()
|
||||
{
|
||||
return LibraryManager.RootFolder.Children
|
||||
.OfType<Folder>()
|
||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
|
||||
return GetPhysicalParents()
|
||||
.SelectMany(c => c.LinkedChildren)
|
||||
.ToList();
|
||||
}
|
||||
|
@ -199,11 +197,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
private IEnumerable<BaseItem> GetActualChildren()
|
||||
{
|
||||
return
|
||||
LibraryManager.RootFolder.Children
|
||||
return GetPhysicalParents().SelectMany(c => c.Children);
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> GetPhysicalParents()
|
||||
{
|
||||
return LibraryManager.RootFolder.Children
|
||||
.OfType<Folder>()
|
||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
|
||||
.SelectMany(c => c.Children);
|
||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public List<Guid> ThemeSongIds { get; set; }
|
||||
public List<Guid> ThemeVideoIds { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
public Folder()
|
||||
{
|
||||
|
@ -36,7 +35,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
ThemeSongIds = new List<Guid>();
|
||||
ThemeVideoIds = new List<Guid>();
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -151,7 +149,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
if (!EnableNewFolderQuerying())
|
||||
{
|
||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool EnableNewFolderQuerying()
|
||||
{
|
||||
return ConfigurationManager.Configuration.MigrationVersion >= 1;
|
||||
}
|
||||
|
||||
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
|
||||
|
@ -196,21 +202,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override string OfficialRatingForComparison
|
||||
{
|
||||
get
|
||||
{
|
||||
// Never want folders to be blocked by "BlockNotRated"
|
||||
if (this is Series)
|
||||
{
|
||||
return base.OfficialRatingForComparison;
|
||||
}
|
||||
|
||||
return !string.IsNullOrWhiteSpace(base.OfficialRatingForComparison) ? base.OfficialRatingForComparison : "None";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the child.
|
||||
/// </summary>
|
||||
|
@ -224,7 +215,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
item.SetParent(null);
|
||||
|
||||
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
|
||||
if (!EnableNewFolderQuerying())
|
||||
{
|
||||
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -457,32 +453,25 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
BaseItem currentChild;
|
||||
|
||||
if (currentChildren.TryGetValue(child.Id, out currentChild))
|
||||
if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child))
|
||||
{
|
||||
if (IsValidFromResolver(currentChild, child))
|
||||
var currentChildLocationType = currentChild.LocationType;
|
||||
if (currentChildLocationType != LocationType.Remote &&
|
||||
currentChildLocationType != LocationType.Virtual)
|
||||
{
|
||||
var currentChildLocationType = currentChild.LocationType;
|
||||
if (currentChildLocationType != LocationType.Remote &&
|
||||
currentChildLocationType != LocationType.Virtual)
|
||||
{
|
||||
currentChild.DateModified = child.DateModified;
|
||||
}
|
||||
currentChild.DateModified = child.DateModified;
|
||||
}
|
||||
|
||||
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
|
||||
validChildren.Add(currentChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
newItems.Add(child);
|
||||
validChildren.Add(child);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Brand new item - needs to be added
|
||||
newItems.Add(child);
|
||||
validChildren.Add(child);
|
||||
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
|
||||
validChildren.Add(currentChild);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Brand new item - needs to be added
|
||||
child.SetParent(this);
|
||||
newItems.Add(child);
|
||||
validChildren.Add(child);
|
||||
}
|
||||
|
||||
// If any items were added or removed....
|
||||
|
@ -508,7 +497,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
else
|
||||
{
|
||||
await UpdateIsOffline(item, false).ConfigureAwait(false);
|
||||
actualRemovals.Add(item);
|
||||
}
|
||||
}
|
||||
|
@ -519,6 +507,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
foreach (var item in actualRemovals)
|
||||
{
|
||||
Logger.Debug("Removed item: " + item.Path);
|
||||
|
||||
item.SetParent(null);
|
||||
item.IsOffline = false;
|
||||
await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false);
|
||||
LibraryManager.ReportItemRemoved(item);
|
||||
}
|
||||
}
|
||||
|
@ -527,7 +520,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
AddChildrenInternal(newItems);
|
||||
|
||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
if (!EnableNewFolderQuerying())
|
||||
{
|
||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,7 +717,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return true;
|
||||
}
|
||||
|
||||
return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -757,19 +753,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
protected IEnumerable<BaseItem> GetCachedChildren()
|
||||
{
|
||||
if (ConfigurationManager.Configuration.DisableStartupScan)
|
||||
if (EnableNewFolderQuerying())
|
||||
{
|
||||
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
||||
//return ItemRepository.GetItems(new InternalItemsQuery
|
||||
//{
|
||||
// ParentId = Id
|
||||
return ItemRepository.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
ParentId = Id
|
||||
|
||||
//}).Items.Select(RetrieveChild).Where(i => i != null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
||||
}).Select(RetrieveChild).Where(i => i != null);
|
||||
}
|
||||
|
||||
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
||||
}
|
||||
|
||||
private BaseItem RetrieveChild(BaseItem child)
|
||||
|
@ -832,19 +825,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets allowed children of an item
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||
{
|
||||
return GetChildren(user, includeLinkedChildren, false);
|
||||
}
|
||||
|
||||
internal IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, bool includeHidden)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
|
@ -856,7 +837,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
var result = new Dictionary<Guid, BaseItem>();
|
||||
|
||||
AddChildren(user, includeLinkedChildren, result, includeHidden, false, null);
|
||||
AddChildren(user, includeLinkedChildren, result, false, null);
|
||||
|
||||
return result.Values;
|
||||
}
|
||||
|
@ -872,29 +853,25 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <param name="user">The user.</param>
|
||||
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <param name="includeHidden">if set to <c>true</c> [include hidden].</param>
|
||||
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter)
|
||||
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter)
|
||||
{
|
||||
foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
|
||||
{
|
||||
if (child.IsVisible(user))
|
||||
{
|
||||
if (includeHidden || !child.IsHiddenFromUser(user))
|
||||
if (filter == null || filter(child))
|
||||
{
|
||||
if (filter == null || filter(child))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
result[child.Id] = child;
|
||||
}
|
||||
|
||||
if (recursive && child.IsFolder)
|
||||
{
|
||||
var folder = (Folder)child;
|
||||
|
||||
folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter);
|
||||
folder.AddChildren(user, includeLinkedChildren, result, true, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -935,7 +912,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
var result = new Dictionary<Guid, BaseItem>();
|
||||
|
||||
AddChildren(user, true, result, false, true, filter);
|
||||
AddChildren(user, true, result, true, filter);
|
||||
|
||||
return result.Values;
|
||||
}
|
||||
|
@ -1184,6 +1161,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
Recursive = true,
|
||||
IsFolder = false,
|
||||
IsUnaired = false
|
||||
|
||||
};
|
||||
|
||||
if (!user.Configuration.DisplayMissingEpisodes)
|
||||
|
@ -1322,4 +1300,4 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
RemoteTrailerIds = new List<Guid>();
|
||||
ThemeSongIds = new List<Guid>();
|
||||
ThemeVideoIds = new List<Guid>();
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
public List<Guid> LocalTrailerIds { get; set; }
|
||||
|
@ -34,12 +33,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
locationType != LocationType.Virtual;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the remote trailers.
|
||||
/// </summary>
|
||||
|
@ -105,9 +98,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
return base.GetDeletePaths();
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Game);
|
||||
return UnratedItem.Game;
|
||||
}
|
||||
|
||||
public GameInfo GetLookupInfo()
|
||||
|
|
|
@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Game;
|
||||
}
|
||||
|
||||
public GameSystemInfo GetLookupInfo()
|
||||
{
|
||||
var id = GetItemLookupInfo<GameSystemInfo>();
|
||||
|
|
|
@ -16,6 +16,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
IEnumerable<string> PhysicalLocations { get; }
|
||||
}
|
||||
|
||||
public interface ISupportsUserSpecificView
|
||||
{
|
||||
bool EnableUserSpecificView { get; }
|
||||
}
|
||||
|
||||
public static class CollectionFolderExtensions
|
||||
{
|
||||
public static string GetViewType(this ICollectionFolder folder, User user)
|
||||
|
|
18
MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs
Normal file
18
MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHiddenFromDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified user is hidden.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns><c>true</c> if the specified user is hidden; otherwise, <c>false</c>.</returns>
|
||||
bool IsHiddenFromUser(User user);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
|
@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public string[] MediaTypes { get; set; }
|
||||
public string[] IncludeItemTypes { get; set; }
|
||||
public string[] ExcludeItemTypes { get; set; }
|
||||
public string[] ExcludeTags { get; set; }
|
||||
public string[] Genres { get; set; }
|
||||
|
||||
public bool? IsMissing { get; set; }
|
||||
|
@ -69,12 +71,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public string[] Studios { get; set; }
|
||||
public string[] StudioIds { get; set; }
|
||||
public string[] GenreIds { get; set; }
|
||||
public ImageType[] ImageTypes { get; set; }
|
||||
public VideoType[] VideoTypes { get; set; }
|
||||
public UnratedItem[] BlockUnratedItems { get; set; }
|
||||
public int[] Years { get; set; }
|
||||
public string[] Tags { get; set; }
|
||||
public string[] OfficialRatings { get; set; }
|
||||
|
||||
public DateTime? MinPremiereDate { get; set; }
|
||||
public DateTime? MinStartDate { get; set; }
|
||||
public DateTime? MaxStartDate { get; set; }
|
||||
public DateTime? MinEndDate { get; set; }
|
||||
|
@ -87,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public int? MinPlayers { get; set; }
|
||||
public int? MaxPlayers { get; set; }
|
||||
public int? MinIndexNumber { get; set; }
|
||||
public double? MinCriticRating { get; set; }
|
||||
public double? MinCommunityRating { get; set; }
|
||||
|
||||
|
@ -101,9 +107,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
public LocationType? LocationType { get; set; }
|
||||
|
||||
public Guid? ParentId { get; set; }
|
||||
public string[] AncestorIds { get; set; }
|
||||
public string[] TopParentIds { get; set; }
|
||||
|
||||
public LocationType[] ExcludeLocationTypes { get; set; }
|
||||
|
||||
public InternalItemsQuery()
|
||||
{
|
||||
BlockUnratedItems = new UnratedItem[] { };
|
||||
Tags = new string[] { };
|
||||
OfficialRatings = new string[] { };
|
||||
SortBy = new string[] { };
|
||||
|
@ -113,6 +124,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
Genres = new string[] { };
|
||||
Studios = new string[] { };
|
||||
StudioIds = new string[] { };
|
||||
GenreIds = new string[] { };
|
||||
ImageTypes = new ImageType[] { };
|
||||
VideoTypes = new VideoType[] { };
|
||||
Years = new int[] { };
|
||||
|
@ -120,6 +132,29 @@ namespace MediaBrowser.Controller.Entities
|
|||
PersonIds = new string[] { };
|
||||
ChannelIds = new string[] { };
|
||||
ItemIds = new string[] { };
|
||||
AncestorIds = new string[] { };
|
||||
TopParentIds = new string[] { };
|
||||
ExcludeTags = new string[] { };
|
||||
ExcludeLocationTypes = new LocationType[] { };
|
||||
}
|
||||
|
||||
public InternalItemsQuery(User user)
|
||||
: this()
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
var policy = user.Policy;
|
||||
MaxParentalRating = policy.MaxParentalRating;
|
||||
|
||||
if (policy.MaxParentalRating.HasValue)
|
||||
{
|
||||
BlockUnratedItems = policy.BlockUnratedItems;
|
||||
}
|
||||
|
||||
ExcludeTags = policy.BlockedTags;
|
||||
|
||||
User = user;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,13 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Movies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BoxSet
|
||||
/// </summary>
|
||||
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares
|
||||
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
|
||||
{
|
||||
public List<Share> Shares { get; set; }
|
||||
|
||||
|
@ -65,6 +63,11 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Movie;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsPreSorted
|
||||
{
|
||||
|
@ -154,34 +157,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
return GetItemLookupInfo<BoxSetInfo>();
|
||||
}
|
||||
|
||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
// Refresh bottom up, children first, then the boxset
|
||||
// By then hopefully the movies within will have Tmdb collection values
|
||||
var items = GetRecursiveChildren().ToList();
|
||||
|
||||
var totalItems = items.Count;
|
||||
var numComplete = 0;
|
||||
|
||||
// Refresh songs
|
||||
foreach (var item in items)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
percent /= totalItems;
|
||||
progress.Report(percent * 100);
|
||||
}
|
||||
|
||||
// Refresh current item
|
||||
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
public override bool IsVisible(User user)
|
||||
{
|
||||
var userId = user.Id.ToString("N");
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
|
||||
// Must have a parent to have special features
|
||||
// In other words, it must be part of the Parent/Child tree
|
||||
if (LocationType == LocationType.FileSystem && Parent != null && !IsInMixedFolder)
|
||||
if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder)
|
||||
{
|
||||
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
@ -159,9 +159,9 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
return itemsChanged;
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
||||
return UnratedItem.Movie;
|
||||
}
|
||||
|
||||
public MovieInfo GetLookupInfo()
|
||||
|
|
|
@ -56,9 +56,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||
return UnratedItem.Music;
|
||||
}
|
||||
|
||||
public MusicVideoInfo GetLookupInfo()
|
||||
|
|
|
@ -101,6 +101,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
public class Photo : BaseItem, IHasTags, IHasTaglines
|
||||
{
|
||||
public List<string> Tags { get; set; }
|
||||
public List<string> Taglines { get; set; }
|
||||
|
||||
public Photo()
|
||||
{
|
||||
Tags = new List<string>();
|
||||
Taglines = new List<string>();
|
||||
}
|
||||
|
||||
|
@ -51,7 +49,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
get
|
||||
{
|
||||
return Parents.OfType<PhotoAlbum>().FirstOrDefault();
|
||||
return GetParents().OfType<PhotoAlbum>().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,10 +68,5 @@ namespace MediaBrowser.Controller.Entities
|
|||
public double? Longitude { get; set; }
|
||||
public double? Altitude { get; set; }
|
||||
public int? IsoSpeedRating { get; set; }
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class PhotoAlbum : Folder, IMetadataContainer
|
||||
public class PhotoAlbum : Folder
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsLocalMetadata
|
||||
{
|
||||
get
|
||||
|
@ -32,31 +33,5 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
||||
}
|
||||
|
||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var items = GetRecursiveChildren().ToList();
|
||||
|
||||
var totalItems = items.Count;
|
||||
var numComplete = 0;
|
||||
|
||||
// Refresh songs
|
||||
foreach (var item in items)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
percent /= totalItems;
|
||||
progress.Report(percent * 100);
|
||||
}
|
||||
|
||||
// Refresh current item
|
||||
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public class Studio : BaseItem, IItemByName, IHasTags
|
||||
{
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
public Studio()
|
||||
{
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
{
|
||||
get
|
||||
{
|
||||
return Season ?? Parent;
|
||||
return Season ?? GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,19 +115,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
return base.CreateUserDataKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our rating comes from our series
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public override string OfficialRatingForComparison
|
||||
{
|
||||
get
|
||||
{
|
||||
var series = Series;
|
||||
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This Episode's Series Instance
|
||||
/// </summary>
|
||||
|
@ -265,14 +252,28 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Guid> GetAncestorIds()
|
||||
{
|
||||
var list = base.GetAncestorIds().ToList();
|
||||
|
||||
var seasonId = SeasonId;
|
||||
|
||||
if (seasonId.HasValue && !list.Contains(seasonId.Value))
|
||||
{
|
||||
list.Add(seasonId.Value);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetDeletePaths()
|
||||
{
|
||||
return new[] { Path };
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Series);
|
||||
return UnratedItem.Series;
|
||||
}
|
||||
|
||||
public EpisodeInfo GetLookupInfo()
|
||||
|
|
|
@ -6,6 +6,7 @@ using MoreLinq;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
|
@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
[IgnoreDataMember]
|
||||
public override BaseItem DisplayParent
|
||||
{
|
||||
get { return Series ?? Parent; }
|
||||
get { return Series ?? GetParent(); }
|
||||
}
|
||||
|
||||
// Genre, Rating and Stuido will all be the same
|
||||
|
@ -87,19 +88,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our rating comes from our series
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public override string OfficialRatingForComparison
|
||||
{
|
||||
get
|
||||
{
|
||||
var series = Series;
|
||||
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
|
@ -234,6 +222,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
return false;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Series;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesName
|
||||
{
|
||||
|
|
|
@ -333,6 +333,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
return config.BlockUnratedItems.Contains(UnratedItem.Series);
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Series;
|
||||
}
|
||||
|
||||
public SeriesInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<SeriesInfo>();
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
get
|
||||
{
|
||||
// Local trailers are not part of children
|
||||
return Parent == null;
|
||||
return GetParent() == null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,9 +97,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
return base.CreateUserDataKey();
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Trailer);
|
||||
return UnratedItem.Trailer;
|
||||
}
|
||||
|
||||
public TrailerInfo GetLookupInfo()
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
public static IUserManager UserManager { get; set; }
|
||||
public static IXmlSerializer XmlSerializer { get; set; }
|
||||
public bool EnableUserViews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// From now on all user paths will be Id-based.
|
||||
|
@ -58,6 +57,26 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
private string _name;
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
|
||||
// lazy load this again
|
||||
SortName = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself
|
||||
|
|
|
@ -55,13 +55,21 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
|
||||
{
|
||||
var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList();
|
||||
list.AddRange(LibraryManager.RootFolder.VirtualChildren);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the children of this folder from the actual file system
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren);
|
||||
return base.GetNonCachedChildren(directoryService);
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh()
|
||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
|
@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public Guid DisplayParentId { get; set; }
|
||||
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
|
||||
public static ITVSeriesManager TVSeriesManager;
|
||||
public static IPlaylistManager PlaylistManager;
|
||||
|
||||
|
@ -24,7 +25,26 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override IEnumerable<Guid> GetIdsForAncestorQuery()
|
||||
{
|
||||
var list = new List<Guid>();
|
||||
|
||||
if (DisplayParentId != Guid.Empty)
|
||||
{
|
||||
list.Add(DisplayParentId);
|
||||
}
|
||||
else if (ParentId != Guid.Empty)
|
||||
{
|
||||
list.Add(ParentId);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(Id);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
||||
{
|
||||
var parent = this as Folder;
|
||||
|
@ -81,16 +101,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
return GetChildren(user, false);
|
||||
}
|
||||
|
||||
public static bool IsExcludedFromGrouping(Folder folder)
|
||||
public static bool IsUserSpecific(Folder folder)
|
||||
{
|
||||
var standaloneTypes = new List<string>
|
||||
{
|
||||
CollectionType.Books,
|
||||
CollectionType.HomeVideos,
|
||||
CollectionType.Photos,
|
||||
CollectionType.Playlists,
|
||||
CollectionType.BoxSets,
|
||||
CollectionType.MusicVideos
|
||||
CollectionType.Playlists
|
||||
};
|
||||
|
||||
var collectionFolder = folder as ICollectionFolder;
|
||||
|
@ -100,25 +115,63 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
var supportsUserSpecific = folder as ISupportsUserSpecificView;
|
||||
if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
|
||||
}
|
||||
|
||||
public static bool IsUserSpecific(Folder folder)
|
||||
public static bool IsEligibleForGrouping(Folder folder)
|
||||
{
|
||||
var standaloneTypes = new List<string>
|
||||
{
|
||||
CollectionType.Playlists,
|
||||
var collectionFolder = folder as ICollectionFolder;
|
||||
return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType);
|
||||
}
|
||||
|
||||
public static bool IsEligibleForGrouping(string viewType)
|
||||
{
|
||||
var types = new[]
|
||||
{
|
||||
CollectionType.Movies,
|
||||
CollectionType.TvShows,
|
||||
string.Empty
|
||||
};
|
||||
|
||||
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsEligibleForEnhancedView(string viewType)
|
||||
{
|
||||
var types = new[]
|
||||
{
|
||||
CollectionType.Movies,
|
||||
CollectionType.TvShows
|
||||
};
|
||||
|
||||
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool EnableOriginalFolder(string viewType)
|
||||
{
|
||||
var types = new[]
|
||||
{
|
||||
CollectionType.Games,
|
||||
CollectionType.Books,
|
||||
CollectionType.MusicVideos,
|
||||
CollectionType.HomeVideos,
|
||||
CollectionType.Photos,
|
||||
CollectionType.Music,
|
||||
CollectionType.BoxSets
|
||||
};
|
||||
|
||||
var collectionFolder = folder as ICollectionFolder;
|
||||
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
if (collectionFolder == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
|
||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
|
|
@ -120,59 +120,34 @@ namespace MediaBrowser.Controller.Entities
|
|||
return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
case CollectionType.Photos:
|
||||
case CollectionType.Books:
|
||||
case CollectionType.HomeVideos:
|
||||
case CollectionType.Games:
|
||||
case CollectionType.MusicVideos:
|
||||
{
|
||||
if (query.Recursive)
|
||||
{
|
||||
return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
|
||||
}
|
||||
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
|
||||
}
|
||||
|
||||
case CollectionType.Folders:
|
||||
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
|
||||
|
||||
case CollectionType.Games:
|
||||
return await GetGameView(user, queryParent, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.Playlists:
|
||||
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.BoxSets:
|
||||
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.Photos:
|
||||
return await GetPhotosView(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.TvShows:
|
||||
return await GetTvView(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.Music:
|
||||
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case CollectionType.Movies:
|
||||
return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.MusicGenres:
|
||||
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.MusicGenre:
|
||||
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.GameGenres:
|
||||
return await GetGameGenres(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.GameGenre:
|
||||
return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.GameSystems:
|
||||
return GetGameSystems(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.LatestGames:
|
||||
return GetLatestGames(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.RecentlyPlayedGames:
|
||||
return GetRecentlyPlayedGames(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.GameFavorites:
|
||||
return GetFavoriteGames(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.TvShowSeries:
|
||||
return GetTvSeries(queryParent, user, query);
|
||||
|
||||
|
@ -212,6 +187,21 @@ namespace MediaBrowser.Controller.Entities
|
|||
case SpecialFolder.MovieCollections:
|
||||
return GetMovieCollections(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.TvFavoriteEpisodes:
|
||||
return GetFavoriteEpisodes(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.TvFavoriteSeries:
|
||||
return GetFavoriteSeries(queryParent, user, query);
|
||||
|
||||
case CollectionType.Music:
|
||||
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.MusicGenres:
|
||||
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.MusicGenre:
|
||||
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
||||
|
||||
case SpecialFolder.MusicLatest:
|
||||
return GetMusicLatest(queryParent, user, query);
|
||||
|
||||
|
@ -230,12 +220,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
case SpecialFolder.MusicSongs:
|
||||
return GetMusicSongs(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.TvFavoriteEpisodes:
|
||||
return GetFavoriteEpisodes(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.TvFavoriteSeries:
|
||||
return GetFavoriteSeries(queryParent, user, query);
|
||||
|
||||
case SpecialFolder.MusicFavorites:
|
||||
return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false);
|
||||
|
||||
|
@ -262,18 +246,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
|
||||
|
||||
return GetResult(list, parent, query);
|
||||
}
|
||||
|
||||
private int GetSpecialItemsLimit()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
if (query.Recursive)
|
||||
|
@ -289,7 +261,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false));
|
||||
//list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicArtists, "4", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false));
|
||||
|
@ -422,6 +394,36 @@ namespace MediaBrowser.Controller.Entities
|
|||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsFavorite = true;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsFavorite = true;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
|
||||
|
||||
return GetResult(list, parent, query);
|
||||
}
|
||||
|
||||
private int GetSpecialItemsLimit()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
if (query.Recursive)
|
||||
|
@ -480,24 +482,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsFavorite = true;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsFavorite = true;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query));
|
||||
|
@ -617,54 +601,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
return GetResult(list, parent, query);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, InternalItemsQuery query)
|
||||
{
|
||||
if (query.Recursive)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query));
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
|
||||
list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false));
|
||||
list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false));
|
||||
|
||||
return GetResult(list, parent, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
|
||||
query.SortOrder = SortOrder.Descending;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsPlayed = true;
|
||||
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
|
||||
query.SortOrder = SortOrder.Descending;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.IsFavorite = true;
|
||||
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
|
||||
|
@ -745,49 +681,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
return GetResult(items, queryParent, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query));
|
||||
|
||||
return PostFilterAndSort(items, parent, null, query);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games },
|
||||
i => i is Game && i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
|
||||
|
||||
return GetResult(items, queryParent, query);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
|
||||
.OfType<Game>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.DistinctNames()
|
||||
.Select(i =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return _libraryManager.GetGameGenre(i);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Full exception logged at lower levels
|
||||
_logger.Error("Error getting game genre");
|
||||
return null;
|
||||
}
|
||||
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent));
|
||||
|
||||
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
return GetResult(genres, parent, query);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
|
||||
where T : BaseItem
|
||||
{
|
||||
|
@ -1061,6 +954,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
if (request.GenreIds.Length > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.VideoTypes.Length > 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -1101,10 +999,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
if (request.MinIndexNumber.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<BaseItem> FilterVirtualEpisodes(
|
||||
private static IEnumerable<BaseItem> FilterVirtualEpisodes(
|
||||
IEnumerable<BaseItem> items,
|
||||
bool? isMissing,
|
||||
bool? isVirtualUnaired,
|
||||
|
@ -1374,7 +1277,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
if (query.IsInBoxSet.HasValue)
|
||||
{
|
||||
var val = query.IsInBoxSet.Value;
|
||||
if (item.Parents.OfType<BoxSet>().Any() != val)
|
||||
if (item.GetParents().OfType<BoxSet>().Any() != val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1657,6 +1560,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
// Apply genre filter
|
||||
if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id =>
|
||||
{
|
||||
var genreItem = libraryManager.GetItemById(id);
|
||||
return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if (query.Years.Length > 0)
|
||||
{
|
||||
|
@ -1779,6 +1692,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
if (query.MinIndexNumber.HasValue)
|
||||
{
|
||||
var val = query.MinIndexNumber.Value;
|
||||
|
||||
if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1789,12 +1712,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
return _libraryManager.RootFolder
|
||||
.Children
|
||||
.OfType<Folder>()
|
||||
.Where(i => !UserView.IsExcludedFromGrouping(i));
|
||||
.Where(UserView.IsEligibleForGrouping);
|
||||
}
|
||||
return user.RootFolder
|
||||
.GetChildren(user, true, true)
|
||||
.GetChildren(user, true)
|
||||
.OfType<Folder>()
|
||||
.Where(i => user.IsFolderGrouped(i.Id) && !UserView.IsExcludedFromGrouping(i));
|
||||
.Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
|
||||
}
|
||||
|
||||
private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
|
||||
|
|
|
@ -185,12 +185,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
public bool IsShortcut { get; set; }
|
||||
public string ShortcutPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the video bit rate.
|
||||
/// </summary>
|
||||
|
@ -356,7 +350,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
// Must have a parent to have additional parts or alternate versions
|
||||
// In other words, it must be part of the Parent/Child tree
|
||||
// The additional parts won't have additional parts themselves
|
||||
if (LocationType == LocationType.FileSystem && Parent != null)
|
||||
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
||||
{
|
||||
if (!IsStacked)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Model.System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace MediaBrowser.Controller
|
||||
{
|
||||
|
@ -63,7 +65,7 @@ namespace MediaBrowser.Controller
|
|||
/// Gets the local ip address.
|
||||
/// </summary>
|
||||
/// <value>The local ip address.</value>
|
||||
string LocalIpAddress { get; }
|
||||
List<IPAddress> LocalIpAddresses { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local API URL.
|
||||
|
|
|
@ -337,7 +337,6 @@ namespace MediaBrowser.Controller.Library
|
|||
string parentId,
|
||||
string viewType,
|
||||
string sortName,
|
||||
string uniqueId,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
|
@ -391,13 +390,11 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="viewType">Type of the view.</param>
|
||||
/// <param name="sortName">Name of the sort.</param>
|
||||
/// <param name="uniqueId">The unique identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<UserView>.</returns>
|
||||
Task<UserView> GetShadowView(BaseItem parent,
|
||||
string viewType,
|
||||
string sortName,
|
||||
string uniqueId,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
|
@ -543,5 +540,29 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="imageIndex">Index of the image.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="parentIds">The parent ids.</param>
|
||||
/// <returns>List<BaseItem>.</returns>
|
||||
IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items result.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="parentIds">The parent ids.</param>
|
||||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the file.
|
||||
/// </summary>
|
||||
/// <param name="file">The file.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
|
||||
}
|
||||
}
|
|
@ -155,7 +155,7 @@ namespace MediaBrowser.Controller.Library
|
|||
// Not officially supported but in some cases we can handle it.
|
||||
if (item == null)
|
||||
{
|
||||
item = parent.Parents.OfType<T>().FirstOrDefault();
|
||||
item = parent.GetParents().OfType<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
return item != null;
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public bool IsLive { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public bool IsPremiere { get; set; }
|
||||
public ProgramAudio? Audio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
|
@ -106,9 +105,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
|
||||
return UnratedItem.LiveTvProgram;
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
|
@ -140,5 +139,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override bool IsVisibleStandalone(User user)
|
||||
{
|
||||
return IsVisible(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
return GetClientTypeName() + "-" + Name;
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel);
|
||||
return UnratedItem.LiveTvChannel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -40,10 +40,11 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the channel.
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The type of the channel.</value>
|
||||
public ChannelType ChannelType { get; set; }
|
||||
/// <value>The name.</value>
|
||||
[IgnoreDataMember]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The start date of the program, in UTC.
|
||||
|
@ -51,12 +52,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
[IgnoreDataMember]
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the audio.
|
||||
/// </summary>
|
||||
/// <value>The audio.</value>
|
||||
public ProgramAudio? Audio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is repeat.
|
||||
/// </summary>
|
||||
|
@ -71,12 +66,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
[IgnoreDataMember]
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the service.
|
||||
/// </summary>
|
||||
/// <value>The name of the service.</value>
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is movie.
|
||||
/// </summary>
|
||||
|
@ -153,14 +142,14 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override string MediaType
|
||||
{
|
||||
get
|
||||
{
|
||||
return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
|
||||
}
|
||||
}
|
||||
//[IgnoreDataMember]
|
||||
//public override string MediaType
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
|
||||
// }
|
||||
//}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsAiring
|
||||
|
@ -189,9 +178,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
return "Program";
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
|
||||
return UnratedItem.LiveTvProgram;
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
|
@ -236,5 +225,14 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
return base.SupportsPeople;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public bool IsLive { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public bool IsPremiere { get; set; }
|
||||
public ProgramAudio? Audio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
|
@ -121,9 +120,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
|
||||
return UnratedItem.LiveTvProgram;
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
|
@ -155,5 +154,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override bool IsVisibleStandalone(User user)
|
||||
{
|
||||
return IsVisible(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
|
@ -11,6 +12,11 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
return false;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.LiveTvProgram;
|
||||
}
|
||||
|
||||
public override bool SupportsLocalMetadata
|
||||
{
|
||||
get
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
<Reference Include="Interfaces.IO">
|
||||
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -65,9 +68,6 @@
|
|||
<Reference Include="ServiceStack.Interfaces">
|
||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
|
@ -162,6 +162,7 @@
|
|||
<Compile Include="Entities\IHasThemeMedia.cs" />
|
||||
<Compile Include="Entities\IHasTrailers.cs" />
|
||||
<Compile Include="Entities\IHasUserData.cs" />
|
||||
<Compile Include="Entities\IHiddenFromDisplay.cs" />
|
||||
<Compile Include="Entities\IItemByName.cs" />
|
||||
<Compile Include="Entities\ILibraryItem.cs" />
|
||||
<Compile Include="Entities\ImageSourceInfo.cs" />
|
||||
|
|
|
@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
/// Extracts the audio image.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="imageStreamIndex">Index of the image stream.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
|
||||
Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the video image.
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
public IIsoMount MountedIso { get; set; }
|
||||
public VideoType VideoType { get; set; }
|
||||
public List<string> PlayableStreamFileNames { get; set; }
|
||||
public bool ExtractKeyFrameInterval { get; set; }
|
||||
|
||||
public MediaInfoRequest()
|
||||
{
|
||||
|
|
|
@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net
|
|||
/// the ssl certificate localtion on the file system.</param>
|
||||
void StartServer(IEnumerable<string> urlPrefixes, string certificatePath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local end points.
|
||||
/// </summary>
|
||||
/// <value>The local end points.</value>
|
||||
IEnumerable<string> LocalEndPoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Stops this instance.
|
||||
/// </summary>
|
||||
|
|
|
@ -176,6 +176,20 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <param name="query">The query.</param>
|
||||
/// <returns>QueryResult<Tuple<Guid, System.String>>.</returns>
|
||||
QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item list.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>List<BaseItem>.</returns>
|
||||
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the inherited values.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateInheritedValues(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ namespace MediaBrowser.Controller.Playlists
|
|||
|
||||
public string PlaylistMediaType { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override string MediaType
|
||||
{
|
||||
get
|
||||
|
|
|
@ -10,24 +10,6 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <value>The item identifier.</value>
|
||||
public Guid ItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the item.
|
||||
/// </summary>
|
||||
/// <value>The name of the item.</value>
|
||||
public string ItemName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the item.
|
||||
/// </summary>
|
||||
/// <value>The type of the item.</value>
|
||||
public string ItemType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the series.
|
||||
/// </summary>
|
||||
/// <value>The name of the series.</value>
|
||||
public string SeriesName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date last metadata refresh.
|
||||
/// </summary>
|
||||
|
@ -40,22 +22,8 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <value>The date last images refresh.</value>
|
||||
public DateTime? DateLastImagesRefresh { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the last result error message.
|
||||
/// </summary>
|
||||
/// <value>The last result error message.</value>
|
||||
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)
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
public interface IResolverIgnoreRule
|
||||
{
|
||||
bool ShouldIgnore(ItemResolveArgs args);
|
||||
bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.1.1" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
</packages>
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
Limit = limit,
|
||||
StartIndex = startIndex,
|
||||
SortBy = sortOrders.ToArray(),
|
||||
SortOrder = sort.SortOrder,
|
||||
User = user,
|
||||
Filter = FilterUnsupportedContent
|
||||
QueryResult<BaseItem> queryResult;
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
if (folder is UserRootFolder)
|
||||
{
|
||||
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<BaseItem>
|
||||
{
|
||||
Items = views.Cast<BaseItem>().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);
|
||||
}
|
||||
|
||||
var options = _config.GetDlnaConfiguration();
|
||||
|
||||
|
@ -481,23 +500,17 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
|
||||
private QueryResult<ServerItem> 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
|
||||
Person = person.Name,
|
||||
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name },
|
||||
SortBy = new[] { ItemSortBy.SortName },
|
||||
Limit = limit,
|
||||
StartIndex = startIndex
|
||||
|
||||
}).Items;
|
||||
}, new string[] { });
|
||||
|
||||
var items = itemsWithPerson
|
||||
.Where(i => i is Movie || i is Series || i is IChannelItem)
|
||||
.Where(i => i.IsVisibleStandalone(user))
|
||||
.ToList();
|
||||
|
||||
items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
|
||||
.Skip(startIndex ?? 0)
|
||||
.Take(limit ?? int.MaxValue)
|
||||
.ToList();
|
||||
|
||||
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<ServerItem>
|
||||
{
|
||||
TotalRecordCount = serverItems.Length,
|
||||
TotalRecordCount = itemsResult.TotalRecordCount,
|
||||
Items = serverItems
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main
|
|||
private readonly List<string> _registeredServerIds = new List<string>();
|
||||
private bool _dlnaServerStarted;
|
||||
|
||||
public DlnaEntryPoint(IServerConfigurationManager config,
|
||||
ILogManager logManager,
|
||||
IServerApplicationHost appHost,
|
||||
INetworkManager network,
|
||||
ISessionManager sessionManager,
|
||||
IHttpClient httpClient,
|
||||
ILibraryManager libraryManager,
|
||||
IUserManager userManager,
|
||||
IDlnaManager dlnaManager,
|
||||
IImageProcessor imageProcessor,
|
||||
IUserDataManager userDataManager,
|
||||
ILocalizationManager localization,
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
public DlnaEntryPoint(IServerConfigurationManager config,
|
||||
ILogManager logManager,
|
||||
IServerApplicationHost appHost,
|
||||
INetworkManager network,
|
||||
ISessionManager sessionManager,
|
||||
IHttpClient httpClient,
|
||||
ILibraryManager libraryManager,
|
||||
IUserManager userManager,
|
||||
IDlnaManager dlnaManager,
|
||||
IImageProcessor imageProcessor,
|
||||
IUserDataManager userDataManager,
|
||||
ILocalizationManager localization,
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
|
||||
{
|
||||
_config = config;
|
||||
|
@ -148,13 +148,20 @@ namespace MediaBrowser.Dlna.Main
|
|||
|
||||
private void RegisterServerEndpoints()
|
||||
{
|
||||
foreach (var address in _network.GetLocalIpAddresses())
|
||||
foreach (var address in _appHost.LocalIpAddresses)
|
||||
{
|
||||
var guid = address.GetMD5();
|
||||
//if (IPAddress.IsLoopback(address))
|
||||
//{
|
||||
// // Should we allow this?
|
||||
// continue;
|
||||
//}
|
||||
|
||||
var addressString = address.ToString();
|
||||
var guid = addressString.GetMD5();
|
||||
|
||||
var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml";
|
||||
|
||||
var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI);
|
||||
var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
|
||||
|
||||
var services = new List<string>
|
||||
{
|
||||
|
@ -165,8 +172,8 @@ namespace MediaBrowser.Dlna.Main
|
|||
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
|
||||
"uuid:" + guid.ToString("N")
|
||||
};
|
||||
|
||||
_ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services);
|
||||
|
||||
_ssdpHandler.RegisterNotification(guid, uri, address, services);
|
||||
|
||||
_registeredServerIds.Add(guid.ToString("N"));
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
{
|
||||
Container = "ts",
|
||||
VideoCodec = "h264",
|
||||
AudioCodec = "mp3",
|
||||
AudioCodec = "ac3,aac,mp3",
|
||||
Type = DlnaProfileType.Video
|
||||
},
|
||||
new TranscodingProfile
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</DirectPlayProfiles>
|
||||
<TranscodingProfiles>
|
||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac,mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
</TranscodingProfiles>
|
||||
<ContainerProfiles>
|
||||
|
|
|
@ -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<SsdpMessageEventArgs> DeviceDiscovered;
|
||||
public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
|
||||
private readonly INetworkManager _networkManager;
|
||||
|
||||
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost)
|
||||
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost, INetworkManager networkManager)
|
||||
{
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_appHost = appHost;
|
||||
_networkManager = networkManager;
|
||||
}
|
||||
|
||||
private List<IPAddress> 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,30 +101,18 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<NetworkInterface> GetNetworkInterfaces()
|
||||
{
|
||||
try
|
||||
{
|
||||
return NetworkInterface.GetAllNetworkInterfaces();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
|
||||
return new List<NetworkInterface>();
|
||||
}
|
||||
}
|
||||
private void CreateListener(IPAddress localIp)
|
||||
{
|
||||
Task.Factory.StartNew(async (o) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var endPoint = new IPEndPoint(localIp, 1900);
|
||||
_logger.Info("Creating SSDP listener on {0}", localIp);
|
||||
|
||||
var endPoint = new IPEndPoint(localIp, 1900);
|
||||
|
||||
var socket = GetMulticastSocket(localIp, endPoint);
|
||||
|
||||
_logger.Info("Creating SSDP listener on {0}", localIp);
|
||||
|
||||
var receiveBuffer = new byte[64000];
|
||||
|
||||
CreateNotifier(localIp);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
</packages>
|
|
@ -79,14 +79,11 @@
|
|||
<Compile Include="Providers\SeriesXmlProvider.cs" />
|
||||
<Compile Include="Providers\VideoXmlProvider.cs" />
|
||||
<Compile Include="Savers\BoxSetXmlSaver.cs" />
|
||||
<Compile Include="Savers\EpisodeXmlSaver.cs" />
|
||||
<Compile Include="Savers\FolderXmlSaver.cs" />
|
||||
<Compile Include="Savers\GameSystemXmlSaver.cs" />
|
||||
<Compile Include="Savers\GameXmlSaver.cs" />
|
||||
<Compile Include="Savers\MovieXmlSaver.cs" />
|
||||
<Compile Include="Savers\PersonXmlSaver.cs" />
|
||||
<Compile Include="Savers\PlaylistXmlSaver.cs" />
|
||||
<Compile Include="Savers\SeriesXmlSaver.cs" />
|
||||
<Compile Include="Savers\XmlSaverHelpers.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is enabled for] [the specified item].
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="updateType">Type of the update.</param>
|
||||
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public void Save(IHasMetadata item, CancellationToken cancellationToken)
|
||||
{
|
||||
var episode = (Episode)item;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.Append("<Item>");
|
||||
|
||||
if (!string.IsNullOrEmpty(item.Name))
|
||||
{
|
||||
builder.Append("<EpisodeName>" + SecurityElement.Escape(episode.Name) + "</EpisodeName>");
|
||||
}
|
||||
|
||||
if (episode.IndexNumber.HasValue)
|
||||
{
|
||||
builder.Append("<EpisodeNumber>" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + "</EpisodeNumber>");
|
||||
}
|
||||
|
||||
if (episode.IndexNumberEnd.HasValue)
|
||||
{
|
||||
builder.Append("<EpisodeNumberEnd>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</EpisodeNumberEnd>");
|
||||
}
|
||||
|
||||
if (episode.AirsAfterSeasonNumber.HasValue)
|
||||
{
|
||||
builder.Append("<airsafter_season>" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "</airsafter_season>");
|
||||
}
|
||||
if (episode.AirsBeforeEpisodeNumber.HasValue)
|
||||
{
|
||||
builder.Append("<airsbefore_episode>" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "</airsbefore_episode>");
|
||||
}
|
||||
if (episode.AirsBeforeSeasonNumber.HasValue)
|
||||
{
|
||||
builder.Append("<airsbefore_season>" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "</airsbefore_season>");
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>");
|
||||
}
|
||||
|
||||
if (episode.AbsoluteEpisodeNumber.HasValue)
|
||||
{
|
||||
builder.Append("<absolute_number>" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "</absolute_number>");
|
||||
}
|
||||
|
||||
if (episode.DvdEpisodeNumber.HasValue)
|
||||
{
|
||||
builder.Append("<DVD_episodenumber>" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "</DVD_episodenumber>");
|
||||
}
|
||||
|
||||
if (episode.DvdSeasonNumber.HasValue)
|
||||
{
|
||||
builder.Append("<DVD_season>" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "</DVD_season>");
|
||||
}
|
||||
|
||||
if (episode.PremiereDate.HasValue)
|
||||
{
|
||||
builder.Append("<FirstAired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
|
||||
}
|
||||
|
||||
XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder);
|
||||
XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository);
|
||||
|
||||
builder.Append("</Item>");
|
||||
|
||||
var xmlFilePath = GetSavePath(item);
|
||||
|
||||
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
|
||||
{
|
||||
"FirstAired",
|
||||
"SeasonNumber",
|
||||
"EpisodeNumber",
|
||||
"EpisodeName",
|
||||
"EpisodeNumberEnd",
|
||||
"airsafter_season",
|
||||
"airsbefore_episode",
|
||||
"airsbefore_season",
|
||||
"DVD_episodenumber",
|
||||
"DVD_season",
|
||||
"absolute_number"
|
||||
|
||||
}, _config, _fileSystem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the save path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public string GetSavePath(IHasMetadata item)
|
||||
{
|
||||
var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml");
|
||||
|
||||
return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Saves movie.xml for movies, trailers and music videos
|
||||
/// </summary>
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is enabled for] [the specified item].
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="updateType">Type of the update.</param>
|
||||
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public void Save(IHasMetadata item, CancellationToken cancellationToken)
|
||||
{
|
||||
var video = (Video)item;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.Append("<Title>");
|
||||
|
||||
XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder);
|
||||
|
||||
var musicVideo = item as MusicVideo;
|
||||
|
||||
if (musicVideo != null)
|
||||
{
|
||||
if (musicVideo.Artists.Count > 0)
|
||||
{
|
||||
builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(musicVideo.Album))
|
||||
{
|
||||
builder.Append("<Album>" + SecurityElement.Escape(musicVideo.Album) + "</Album>");
|
||||
}
|
||||
}
|
||||
|
||||
var movie = item as Movie;
|
||||
|
||||
if (movie != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
|
||||
{
|
||||
builder.Append("<TmdbCollectionName>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</TmdbCollectionName>");
|
||||
}
|
||||
}
|
||||
|
||||
XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository);
|
||||
|
||||
builder.Append("</Title>");
|
||||
|
||||
var xmlFilePath = GetSavePath(item);
|
||||
|
||||
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is enabled for] [the specified item].
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="updateType">Type of the update.</param>
|
||||
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||
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");
|
||||
|
||||
/// <summary>
|
||||
/// Saves the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public void Save(IHasMetadata item, CancellationToken cancellationToken)
|
||||
{
|
||||
var series = (Series)item;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.Append("<Series>");
|
||||
|
||||
var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
|
||||
|
||||
if (!string.IsNullOrEmpty(tvdb))
|
||||
{
|
||||
builder.Append("<id>" + SecurityElement.Escape(tvdb) + "</id>");
|
||||
}
|
||||
|
||||
if (series.Status.HasValue)
|
||||
{
|
||||
builder.Append("<Status>" + SecurityElement.Escape(series.Status.Value.ToString()) + "</Status>");
|
||||
}
|
||||
|
||||
if (series.Studios.Count > 0)
|
||||
{
|
||||
builder.Append("<Network>" + SecurityElement.Escape(series.Studios[0]) + "</Network>");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(series.AirTime))
|
||||
{
|
||||
builder.Append("<Airs_Time>" + SecurityElement.Escape(series.AirTime) + "</Airs_Time>");
|
||||
}
|
||||
|
||||
if (series.AirDays != null)
|
||||
{
|
||||
if (series.AirDays.Count == 7)
|
||||
{
|
||||
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape("Daily") + "</Airs_DayOfWeek>");
|
||||
}
|
||||
else if (series.AirDays.Count > 0)
|
||||
{
|
||||
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
|
||||
}
|
||||
}
|
||||
|
||||
if (series.PremiereDate.HasValue)
|
||||
{
|
||||
builder.Append("<FirstAired>" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
|
||||
}
|
||||
|
||||
if (series.AnimeSeriesIndex.HasValue)
|
||||
{
|
||||
builder.Append("<AnimeSeriesIndex>" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "</AnimeSeriesIndex>");
|
||||
}
|
||||
|
||||
XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder);
|
||||
|
||||
builder.Append("</Series>");
|
||||
|
||||
var xmlFilePath = GetSavePath(item);
|
||||
|
||||
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
|
||||
{
|
||||
"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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the save path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public string GetSavePath(IHasMetadata item)
|
||||
{
|
||||
return Path.Combine(item.Path, "series.xml");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
|
||||
public Task<Stream> 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<Stream> 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<Stream> ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio,
|
||||
private async Task<Stream> 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<Stream> ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
private async Task<Stream> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(inputPath))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var inputFormat = subtitle.Item2;
|
||||
|
||||
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
|
||||
{
|
||||
return subtitle.Item1;
|
||||
}
|
||||
|
||||
using (var stream = subtitle.Item1)
|
||||
{
|
||||
var inputFormat = subtitle.Item2;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -827,6 +827,9 @@
|
|||
<Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
|
||||
<Link>MediaInfo\VideoCodec.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
|
||||
<Link>Net\EndPointInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
|
||||
<Link>Net\HttpException.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -783,6 +783,9 @@
|
|||
<Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
|
||||
<Link>MediaInfo\VideoCodec.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
|
||||
<Link>Net\EndPointInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
|
||||
<Link>Net\HttpException.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -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" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,12 @@ namespace MediaBrowser.Model.Configuration
|
|||
/// <value><c>true</c> if this instance is port authorized; otherwise, <c>false</c>.</value>
|
||||
public bool IsPortAuthorized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable high quality image scaling].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable high quality image scaling]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableHighQualityImageScaling { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item by name path.
|
||||
/// </summary>
|
||||
|
@ -92,24 +98,6 @@ namespace MediaBrowser.Model.Configuration
|
|||
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableLocalizedGuids { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [disable startup scan].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [disable startup scan]; otherwise, <c>false</c>.</value>
|
||||
public bool DisableStartupScan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable user views].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable user views]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableUserViews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable library metadata sub folder].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable library metadata sub folder]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableLibraryMetadataSubFolder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the preferred metadata language.
|
||||
/// </summary>
|
||||
|
@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||
/// </summary>
|
||||
public ServerConfiguration()
|
||||
{
|
||||
Migrations = new string[] {};
|
||||
Migrations = new string[] { };
|
||||
|
||||
ImageSavingConvention = ImageSavingConvention.Compatible;
|
||||
PublicPort = 8096;
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities
|
|||
/// <value>The language.</value>
|
||||
public string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the comment.
|
||||
/// </summary>
|
||||
/// <value>The comment.</value>
|
||||
public string Comment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is interlaced.
|
||||
/// </summary>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user