Merge branch 'dev' into beta
This commit is contained in:
commit
16de4de003
|
@ -183,50 +183,6 @@ namespace MediaBrowser.Api
|
||||||
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
|
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>
|
/// <summary>
|
||||||
/// Deslugs an artist name by finding the correct entry in the library
|
/// Deslugs an artist name by finding the correct entry in the library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -102,12 +102,16 @@ namespace MediaBrowser.Api
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetGameSystemSummaries request)
|
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>()
|
.Cast<GameSystem>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
|
|
||||||
|
|
||||||
var result = gameSystems
|
var result = gameSystems
|
||||||
.Select(i => GetSummary(i, user))
|
.Select(i => GetSummary(i, user))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -119,8 +123,15 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
public object Get(GetPlayerIndex request)
|
public object Get(GetPlayerIndex request)
|
||||||
{
|
{
|
||||||
var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game)
|
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
|
||||||
.Cast<Game>();
|
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
|
var lookup = games
|
||||||
.ToLookup(i => i.PlayersSupported ?? -1)
|
.ToLookup(i => i.PlayersSupported ?? -1)
|
||||||
|
|
|
@ -424,7 +424,7 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
public object Get(GetMediaFolders request)
|
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)
|
if (request.IsHidden.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -618,7 +618,7 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
BaseItem parent = item.Parent;
|
BaseItem parent = item.GetParent();
|
||||||
|
|
||||||
while (parent != null)
|
while (parent != null)
|
||||||
{
|
{
|
||||||
|
@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
|
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
|
||||||
|
|
||||||
parent = parent.Parent;
|
parent = parent.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return baseItemDtos.ToList();
|
return baseItemDtos.ToList();
|
||||||
|
@ -637,7 +637,7 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
private BaseItem TranslateParentItem(BaseItem item, User user)
|
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));
|
return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
|
||||||
}
|
}
|
||||||
|
@ -685,6 +685,50 @@ namespace MediaBrowser.Api.Library
|
||||||
return ToOptimizedSerializedResultUsingCache(counts);
|
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)
|
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(userId))
|
if (!string.IsNullOrWhiteSpace(userId))
|
||||||
|
@ -847,9 +891,9 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _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);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
@ -890,9 +934,9 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _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);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
|
@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
|
||||||
public async Task<object> Get(GetSimilarMovies request)
|
public async Task<object> Get(GetSimilarMovies request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = await GetSimilarItemsResult(
|
||||||
// Strip out secondary versions
|
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||||
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
|
||||||
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
@ -128,10 +125,7 @@ namespace MediaBrowser.Api.Movies
|
||||||
public async Task<object> Get(GetSimilarTrailers request)
|
public async Task<object> Get(GetSimilarTrailers request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = await GetSimilarItemsResult(
|
||||||
// Strip out secondary versions
|
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||||
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
|
||||||
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
@ -140,8 +134,12 @@ namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
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);
|
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
var listEligibleForCategories = new List<BaseItem>();
|
||||||
|
@ -184,21 +182,27 @@ namespace MediaBrowser.Api.Movies
|
||||||
return ToOptimizedResult(result);
|
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 user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
var item = string.IsNullOrEmpty(request.Id) ?
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
var inputItems = user == null
|
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||||
? _libraryManager.RootFolder.GetRecursiveChildren(filter)
|
};
|
||||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
var parentIds = new string[] { };
|
||||||
|
var list = _libraryManager.GetItems(query, parentIds)
|
||||||
var list = inputItems.ToList();
|
.Where(i =>
|
||||||
|
{
|
||||||
|
// Strip out secondary versions
|
||||||
|
var v = i as Video;
|
||||||
|
return v != null && !v.PrimaryVersionId.HasValue;
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
|
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
|
||||||
{
|
{
|
||||||
|
@ -379,9 +383,10 @@ namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
foreach (var name in names)
|
foreach (var name in names)
|
||||||
{
|
{
|
||||||
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery
|
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Person = name
|
Person = name
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var items = allMovies
|
var items = allMovies
|
||||||
|
|
|
@ -284,7 +284,7 @@ namespace MediaBrowser.Api
|
||||||
private T GetParentWithImage<T>(BaseItem item, ImageType type)
|
private T GetParentWithImage<T>(BaseItem item, ImageType type)
|
||||||
where T : BaseItem
|
where T : BaseItem
|
||||||
{
|
{
|
||||||
return item.Parents.OfType<T>().FirstOrDefault(i => i.HasImage(type));
|
return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,7 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
_config.Configuration.IsStartupWizardCompleted = true;
|
_config.Configuration.IsStartupWizardCompleted = true;
|
||||||
_config.Configuration.EnableLocalizedGuids = true;
|
_config.Configuration.EnableLocalizedGuids = true;
|
||||||
_config.Configuration.EnableLibraryMetadataSubFolder = true;
|
|
||||||
_config.Configuration.EnableCustomPathSubFolders = true;
|
_config.Configuration.EnableCustomPathSubFolders = true;
|
||||||
_config.Configuration.DisableStartupScan = true;
|
|
||||||
_config.Configuration.EnableUserViews = true;
|
|
||||||
_config.Configuration.EnableDateLastRefresh = true;
|
_config.Configuration.EnableDateLastRefresh = true;
|
||||||
_config.Configuration.MergeMetadataAndImagesByName = true;
|
_config.Configuration.MergeMetadataAndImagesByName = true;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
|
|
|
@ -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")]
|
[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; }
|
public string StartItemId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Skips over a given number of items within the results. Use for paging.
|
/// Skips over a given number of items within the results. Use for paging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -273,29 +273,28 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
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 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 options = GetDtoOptions(request);
|
||||||
|
|
||||||
var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray();
|
var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new ItemsResult
|
||||||
{
|
{
|
||||||
TotalRecordCount = itemsList.Count,
|
TotalRecordCount = itemsResult.TotalRecordCount,
|
||||||
Items = returnItems
|
Items = returnItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -440,7 +439,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
episodes = season.GetEpisodes(user);
|
episodes = season.GetEpisodes(user);
|
||||||
}
|
}
|
||||||
else if (request.Season.HasValue)
|
else if (request.Season.HasValue)
|
||||||
{
|
{
|
||||||
var series = _libraryManager.GetItemById(request.Id) as Series;
|
var series = _libraryManager.GetItemById(request.Id) as Series;
|
||||||
|
@ -495,7 +494,7 @@ namespace MediaBrowser.Api
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
|
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user)
|
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)]
|
[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 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)]
|
[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; }
|
public string OfficialRatings { get; set; }
|
||||||
|
|
||||||
|
@ -385,6 +387,11 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string[] GetGenreIds()
|
||||||
|
{
|
||||||
|
return (GenreIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
public string[] GetPersonTypes()
|
public string[] GetPersonTypes()
|
||||||
{
|
{
|
||||||
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
|
@ -112,6 +112,11 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
||||||
parentItem;
|
parentItem;
|
||||||
|
|
||||||
|
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
|
||||||
|
}
|
||||||
|
|
||||||
// Default list type = children
|
// Default list type = children
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Ids))
|
if (!string.IsNullOrEmpty(request.Ids))
|
||||||
|
@ -211,6 +216,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
Tags = request.GetTags(),
|
Tags = request.GetTags(),
|
||||||
OfficialRatings = request.GetOfficialRatings(),
|
OfficialRatings = request.GetOfficialRatings(),
|
||||||
Genres = request.GetGenres(),
|
Genres = request.GetGenres(),
|
||||||
|
GenreIds = request.GetGenreIds(),
|
||||||
Studios = request.GetStudios(),
|
Studios = request.GetStudios(),
|
||||||
StudioIds = request.GetStudioIds(),
|
StudioIds = request.GetStudioIds(),
|
||||||
Person = request.Person,
|
Person = request.Person,
|
||||||
|
@ -423,15 +429,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min index number
|
|
||||||
if (request.MinIndexNumber.HasValue)
|
|
||||||
{
|
|
||||||
if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min official rating
|
// Min official rating
|
||||||
if (!string.IsNullOrEmpty(request.MinOfficialRating))
|
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")]
|
[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 bool? IncludeExternalContent { get; set; }
|
||||||
|
|
||||||
|
public string PresetViews { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Users/{UserId}/SpecialViewOptions", "GET")]
|
[Route("/Users/{UserId}/SpecialViewOptions", "GET")]
|
||||||
|
@ -75,9 +77,24 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
query.IncludeExternalContent = request.IncludeExternalContent.Value;
|
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 folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
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);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
@ -123,7 +140,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
var views = user.RootFolder
|
var views = user.RootFolder
|
||||||
.GetChildren(user, true)
|
.GetChildren(user, true)
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.Where(i => !UserView.IsExcludedFromGrouping(i))
|
.Where(UserView.IsEligibleForGrouping)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var list = views
|
var list = views
|
||||||
|
@ -141,9 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
|
|
||||||
private bool IsEligibleForSpecialView(ICollectionFolder view)
|
private bool IsEligibleForSpecialView(ICollectionFolder view)
|
||||||
{
|
{
|
||||||
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
|
return UserView.IsEligibleForEnhancedView(view.CollectionType);
|
||||||
|
|
||||||
return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
|
||||||
|
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
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()
|
protected override string CreateUserDataKey()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
|
@ -20,6 +21,11 @@ namespace MediaBrowser.Controller.Channels
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.ChannelContent;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsLocalMetadata
|
public override bool SupportsLocalMetadata
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,9 +42,9 @@ namespace MediaBrowser.Controller.Channels
|
||||||
return ExternalId;
|
return ExternalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
|
return UnratedItem.ChannelContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
public ExtraType? ExtraType { 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]
|
[IgnoreDataMember]
|
||||||
public bool IsThemeMedia
|
public bool IsThemeMedia
|
||||||
{
|
{
|
||||||
|
@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
Artists = new List<string>();
|
Artists = new List<string>();
|
||||||
AlbumArtists = new List<string>();
|
AlbumArtists = new List<string>();
|
||||||
Tags = new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
locationType != LocationType.Virtual;
|
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]
|
[IgnoreDataMember]
|
||||||
public List<string> AllArtists
|
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]
|
[IgnoreDataMember]
|
||||||
public MusicAlbum AlbumEntity
|
public MusicAlbum AlbumEntity
|
||||||
{
|
{
|
||||||
|
@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return base.CreateUserDataKey();
|
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()
|
public SongInfo GetLookupInfo()
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Parents.OfType<MusicArtist>().FirstOrDefault();
|
return GetParents().OfType<MusicArtist>().FirstOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,13 +114,18 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Music;
|
||||||
|
}
|
||||||
|
|
||||||
public AlbumInfo GetLookupInfo()
|
public AlbumInfo GetLookupInfo()
|
||||||
{
|
{
|
||||||
var id = GetItemLookupInfo<AlbumInfo>();
|
var id = GetItemLookupInfo<AlbumInfo>();
|
||||||
|
|
||||||
id.AlbumArtists = AlbumArtists;
|
id.AlbumArtists = AlbumArtists;
|
||||||
|
|
||||||
var artist = Parents.OfType<MusicArtist>().FirstOrDefault();
|
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
|
||||||
|
|
||||||
if (artist != null)
|
if (artist != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Music;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var items = GetRecursiveChildren().ToList();
|
var items = GetRecursiveChildren().ToList();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Collections;
|
using MediaBrowser.Controller.Collections;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
@ -24,6 +23,7 @@ using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
protected BaseItem()
|
protected BaseItem()
|
||||||
{
|
{
|
||||||
|
Tags = new List<string>();
|
||||||
Genres = new List<string>();
|
Genres = new List<string>();
|
||||||
Studios = new List<string>();
|
Studios = new List<string>();
|
||||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported image extensions
|
/// The supported image extensions
|
||||||
/// </summary>
|
/// </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();
|
public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
|
||||||
|
|
||||||
|
@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name
|
[IgnoreDataMember]
|
||||||
|
public virtual string Name
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -122,14 +124,23 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the id.
|
/// Gets or sets the id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The id.</value>
|
/// <value>The id.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance is hd.
|
/// Gets or sets a value indicating whether this instance is hd.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public bool? IsHD { get; set; }
|
public bool? IsHD { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the audio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The audio.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public ProgramAudio? Audio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the id that should be used to key display prefs for this item.
|
/// 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.
|
/// 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.
|
/// Gets or sets the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The path.</value>
|
/// <value>The path.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public virtual string Path { get; set; }
|
public virtual string Path { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id of the program.
|
/// If this content came from an external service, the id of the content on that service
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string ExternalId
|
public string ExternalId
|
||||||
|
@ -201,11 +213,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool IsHiddenFromUser(User user)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual bool IsOwnedItem
|
public virtual bool IsOwnedItem
|
||||||
{
|
{
|
||||||
|
@ -325,12 +332,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the date created.
|
/// Gets or sets the date created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The date created.</value>
|
/// <value>The date created.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public DateTime DateCreated { get; set; }
|
public DateTime DateCreated { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the date modified.
|
/// Gets or sets the date modified.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The date modified.</value>
|
/// <value>The date modified.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public DateTime DateModified { get; set; }
|
public DateTime DateModified { get; set; }
|
||||||
|
|
||||||
public DateTime DateLastSaved { get; set; }
|
public DateTime DateLastSaved { get; set; }
|
||||||
|
@ -407,6 +416,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the name of the forced sort.
|
/// Gets or sets the name of the forced sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name of the forced sort.</value>
|
/// <value>The name of the forced sort.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string ForcedSortName
|
public string ForcedSortName
|
||||||
{
|
{
|
||||||
get { return _forcedSortName; }
|
get { return _forcedSortName; }
|
||||||
|
@ -447,10 +457,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
var idString = Id.ToString("N");
|
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);
|
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
|
||||||
}
|
}
|
||||||
|
@ -493,6 +500,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return sortable;
|
return sortable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
public Guid ParentId { get; set; }
|
public Guid ParentId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -502,15 +510,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Folder Parent
|
public Folder Parent
|
||||||
{
|
{
|
||||||
get
|
get { return GetParent() as Folder; }
|
||||||
{
|
|
||||||
if (ParentId != Guid.Empty)
|
|
||||||
{
|
|
||||||
return LibraryManager.GetItemById(ParentId) as Folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -525,16 +525,28 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public IEnumerable<Folder> Parents
|
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)
|
return null;
|
||||||
{
|
}
|
||||||
yield return parent;
|
|
||||||
|
|
||||||
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>()
|
public T FindParent<T>()
|
||||||
where T : Folder
|
where T : Folder
|
||||||
{
|
{
|
||||||
return Parents.OfType<T>().FirstOrDefault();
|
return GetParents().OfType<T>().FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual BaseItem DisplayParent
|
public virtual BaseItem DisplayParent
|
||||||
{
|
{
|
||||||
get { return Parent; }
|
get { return GetParent(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The premiere date.</value>
|
/// <value>The premiere date.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public DateTime? PremiereDate { get; set; }
|
public DateTime? PremiereDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the display type of the media.
|
/// Gets or sets the display type of the media.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The display type of the media.</value>
|
/// <value>The display type of the media.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string DisplayMediaType { get; set; }
|
public string DisplayMediaType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the official rating.
|
/// Gets or sets the official rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The official rating.</value>
|
/// <value>The official rating.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string OfficialRating { get; set; }
|
public string OfficialRating { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the official rating description.
|
/// Gets or sets the official rating description.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The official rating description.</value>
|
/// <value>The official rating description.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string OfficialRatingDescription { get; set; }
|
public string OfficialRatingDescription { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the custom rating.
|
/// Gets or sets the custom rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The custom rating.</value>
|
/// <value>The custom rating.</value>
|
||||||
//[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string CustomRating { get; set; }
|
public string CustomRating { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the overview.
|
/// Gets or sets the overview.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The overview.</value>
|
/// <value>The overview.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the genres.
|
/// Gets or sets the genres.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The genres.</value>
|
/// <value>The genres.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the tags.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The tags.</value>
|
||||||
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the home page URL.
|
/// Gets or sets the home page URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The home page URL.</value>
|
/// <value>The home page URL.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string HomePageUrl { get; set; }
|
public string HomePageUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the community rating.
|
/// Gets or sets the community rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The community rating.</value>
|
/// <value>The community rating.</value>
|
||||||
//[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public float? CommunityRating { get; set; }
|
public float? CommunityRating { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the community rating vote count.
|
/// Gets or sets the community rating vote count.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The community rating vote count.</value>
|
/// <value>The community rating vote count.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public int? VoteCount { get; set; }
|
public int? VoteCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the run time ticks.
|
/// Gets or sets the run time ticks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The run time ticks.</value>
|
/// <value>The run time ticks.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public long? RunTimeTicks { get; set; }
|
public long? RunTimeTicks { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the production year.
|
/// Gets or sets the production year.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The production year.</value>
|
/// <value>The production year.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public int? ProductionYear { get; set; }
|
public int? ProductionYear { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// This could be episode number, album track number, etc.
|
/// This could be episode number, album track number, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The index number.</value>
|
/// <value>The index number.</value>
|
||||||
//[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public int? IndexNumber { get; set; }
|
public int? IndexNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For an episode this could be the season number, or for a song this could be the disc number.
|
/// For an episode this could be the season number, or for a song this could be the disc number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The parent index number.</value>
|
/// <value>The parent index number.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public int? ParentIndexNumber { get; set; }
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[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]
|
[IgnoreDataMember]
|
||||||
|
@ -721,21 +764,21 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return LibraryManager.ResolvePaths(files, directoryService, null)
|
return LibraryManager.ResolvePaths(files, directoryService, null)
|
||||||
.OfType<Audio.Audio>()
|
.OfType<Audio.Audio>()
|
||||||
.Select(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
|
return audio;
|
||||||
}).OrderBy(i => i.Path).ToList();
|
|
||||||
|
// Sort them so that the list can be easily compared for changes
|
||||||
|
}).OrderBy(i => i.Path).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -751,21 +794,21 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return LibraryManager.ResolvePaths(files, directoryService, null)
|
return LibraryManager.ResolvePaths(files, directoryService, null)
|
||||||
.OfType<Video>()
|
.OfType<Video>()
|
||||||
.Select(item =>
|
.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
|
return item;
|
||||||
}).OrderBy(i => i.Path).ToList();
|
|
||||||
|
// Sort them so that the list can be easily compared for changes
|
||||||
|
}).OrderBy(i => i.Path).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task RefreshMetadata(CancellationToken cancellationToken)
|
public Task RefreshMetadata(CancellationToken cancellationToken)
|
||||||
|
@ -821,7 +864,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected virtual bool SupportsOwnedItems
|
protected virtual bool SupportsOwnedItems
|
||||||
{
|
{
|
||||||
get { return IsFolder || Parent != null; }
|
get { return IsFolder || GetParent() != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -846,7 +889,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
var localTrailersChanged = false;
|
var localTrailersChanged = false;
|
||||||
|
|
||||||
if (LocationType == LocationType.FileSystem && Parent != null)
|
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
||||||
{
|
{
|
||||||
var hasThemeMedia = this as IHasThemeMedia;
|
var hasThemeMedia = this as IHasThemeMedia;
|
||||||
if (hasThemeMedia != null)
|
if (hasThemeMedia != null)
|
||||||
|
@ -1008,7 +1051,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(lang))
|
if (string.IsNullOrWhiteSpace(lang))
|
||||||
{
|
{
|
||||||
lang = Parents
|
lang = GetParents()
|
||||||
.Select(i => i.PreferredMetadataLanguage)
|
.Select(i => i.PreferredMetadataLanguage)
|
||||||
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1081,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(lang))
|
if (string.IsNullOrWhiteSpace(lang))
|
||||||
{
|
{
|
||||||
lang = Parents
|
lang = GetParents()
|
||||||
.Select(i => i.PreferredMetadataCountryCode)
|
.Select(i => i.PreferredMetadataCountryCode)
|
||||||
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
||||||
}
|
}
|
||||||
|
@ -1119,6 +1162,23 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? GetParentalRatingValue()
|
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;
|
var rating = CustomRatingForComparison;
|
||||||
|
|
||||||
|
@ -1156,6 +1216,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Other;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the block unrated value.
|
/// Gets the block unrated value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1174,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
return config.BlockUnratedItems.Contains(GetBlockUnratedType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1206,14 +1271,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parents.Any(i => !i.IsVisible(user)))
|
if (GetParents().Any(i => !i.IsVisible(user)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkFolders)
|
if (checkFolders)
|
||||||
{
|
{
|
||||||
var topParent = Parents.LastOrDefault() ?? this;
|
var topParent = GetParents().LastOrDefault() ?? this;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(topParent.Path))
|
if (string.IsNullOrWhiteSpace(topParent.Path))
|
||||||
{
|
{
|
||||||
|
@ -1307,15 +1372,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return null;
|
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>
|
/// <summary>
|
||||||
/// Adds a studio to the item
|
/// Adds a studio to the item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1779,8 +1835,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ProviderIds = ProviderIds,
|
ProviderIds = ProviderIds,
|
||||||
IndexNumber = IndexNumber,
|
IndexNumber = IndexNumber,
|
||||||
ParentIndexNumber = ParentIndexNumber,
|
ParentIndexNumber = ParentIndexNumber,
|
||||||
Year = ProductionYear,
|
Year = ProductionYear,
|
||||||
PremiereDate = PremiereDate
|
PremiereDate = PremiereDate
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1875,5 +1931,54 @@ namespace MediaBrowser.Controller.Entities
|
||||||
DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture)
|
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 string SeriesName { get; set; }
|
||||||
|
|
||||||
public Book()
|
|
||||||
{
|
|
||||||
Tags = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanDownload()
|
public override bool CanDownload()
|
||||||
{
|
{
|
||||||
var locationType = LocationType;
|
var locationType = LocationType;
|
||||||
|
@ -37,9 +26,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
locationType != LocationType.Virtual;
|
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()
|
public BookInfo GetLookupInfo()
|
||||||
|
@ -48,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(SeriesName))
|
if (string.IsNullOrEmpty(SeriesName))
|
||||||
{
|
{
|
||||||
info.SeriesName = Parents.Select(i => i.Name).FirstOrDefault();
|
info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -181,9 +181,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
private List<LinkedChild> GetLinkedChildrenInternal()
|
private List<LinkedChild> GetLinkedChildrenInternal()
|
||||||
{
|
{
|
||||||
return LibraryManager.RootFolder.Children
|
return GetPhysicalParents()
|
||||||
.OfType<Folder>()
|
|
||||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
|
|
||||||
.SelectMany(c => c.LinkedChildren)
|
.SelectMany(c => c.LinkedChildren)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
@ -199,11 +197,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private IEnumerable<BaseItem> GetActualChildren()
|
private IEnumerable<BaseItem> GetActualChildren()
|
||||||
{
|
{
|
||||||
return
|
return GetPhysicalParents().SelectMany(c => c.Children);
|
||||||
LibraryManager.RootFolder.Children
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Folder> GetPhysicalParents()
|
||||||
|
{
|
||||||
|
return LibraryManager.RootFolder.Children
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
|
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
|
||||||
.SelectMany(c => c.Children);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
|
|
||||||
public Folder()
|
public Folder()
|
||||||
{
|
{
|
||||||
|
@ -36,7 +35,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
ThemeSongIds = new List<Guid>();
|
ThemeSongIds = new List<Guid>();
|
||||||
ThemeVideoIds = new List<Guid>();
|
ThemeVideoIds = new List<Guid>();
|
||||||
Tags = new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -151,7 +149,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
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)
|
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>
|
/// <summary>
|
||||||
/// Removes the child.
|
/// Removes the child.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -224,7 +215,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
item.SetParent(null);
|
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>
|
/// <summary>
|
||||||
|
@ -457,32 +453,25 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
BaseItem currentChild;
|
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;
|
currentChild.DateModified = child.DateModified;
|
||||||
if (currentChildLocationType != LocationType.Remote &&
|
}
|
||||||
currentChildLocationType != LocationType.Virtual)
|
|
||||||
{
|
|
||||||
currentChild.DateModified = child.DateModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
|
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
|
||||||
validChildren.Add(currentChild);
|
validChildren.Add(currentChild);
|
||||||
}
|
|
||||||
else
|
continue;
|
||||||
{
|
|
||||||
newItems.Add(child);
|
|
||||||
validChildren.Add(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Brand new item - needs to be added
|
|
||||||
newItems.Add(child);
|
|
||||||
validChildren.Add(child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Brand new item - needs to be added
|
||||||
|
child.SetParent(this);
|
||||||
|
newItems.Add(child);
|
||||||
|
validChildren.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any items were added or removed....
|
// If any items were added or removed....
|
||||||
|
@ -508,7 +497,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await UpdateIsOffline(item, false).ConfigureAwait(false);
|
|
||||||
actualRemovals.Add(item);
|
actualRemovals.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,6 +507,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
foreach (var item in actualRemovals)
|
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);
|
LibraryManager.ReportItemRemoved(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +520,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
AddChildrenInternal(newItems);
|
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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -757,19 +753,16 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
protected IEnumerable<BaseItem> GetCachedChildren()
|
protected IEnumerable<BaseItem> GetCachedChildren()
|
||||||
{
|
{
|
||||||
if (ConfigurationManager.Configuration.DisableStartupScan)
|
if (EnableNewFolderQuerying())
|
||||||
{
|
{
|
||||||
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
return ItemRepository.GetItemList(new InternalItemsQuery
|
||||||
//return ItemRepository.GetItems(new InternalItemsQuery
|
{
|
||||||
//{
|
ParentId = Id
|
||||||
// ParentId = Id
|
|
||||||
|
|
||||||
//}).Items.Select(RetrieveChild).Where(i => i != null);
|
}).Select(RetrieveChild).Where(i => i != null);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BaseItem RetrieveChild(BaseItem child)
|
private BaseItem RetrieveChild(BaseItem child)
|
||||||
|
@ -832,19 +825,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
|
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)
|
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)
|
if (user == null)
|
||||||
{
|
{
|
||||||
|
@ -856,7 +837,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
var result = new Dictionary<Guid, BaseItem>();
|
var result = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
AddChildren(user, includeLinkedChildren, result, includeHidden, false, null);
|
AddChildren(user, includeLinkedChildren, result, false, null);
|
||||||
|
|
||||||
return result.Values;
|
return result.Values;
|
||||||
}
|
}
|
||||||
|
@ -872,29 +853,25 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
||||||
/// <param name="result">The result.</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="recursive">if set to <c>true</c> [recursive].</param>
|
||||||
/// <param name="filter">The filter.</param>
|
/// <param name="filter">The filter.</param>
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
/// <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))
|
foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
|
||||||
{
|
{
|
||||||
if (child.IsVisible(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)
|
if (recursive && child.IsFolder)
|
||||||
{
|
{
|
||||||
var folder = (Folder)child;
|
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>();
|
var result = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
AddChildren(user, true, result, false, true, filter);
|
AddChildren(user, true, result, true, filter);
|
||||||
|
|
||||||
return result.Values;
|
return result.Values;
|
||||||
}
|
}
|
||||||
|
@ -1184,6 +1161,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsFolder = false,
|
IsFolder = false,
|
||||||
IsUnaired = false
|
IsUnaired = false
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!user.Configuration.DisplayMissingEpisodes)
|
if (!user.Configuration.DisplayMissingEpisodes)
|
||||||
|
@ -1322,4 +1300,4 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
ThemeSongIds = new List<Guid>();
|
ThemeSongIds = new List<Guid>();
|
||||||
ThemeVideoIds = new List<Guid>();
|
ThemeVideoIds = new List<Guid>();
|
||||||
Tags = new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
@ -34,12 +33,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
locationType != LocationType.Virtual;
|
locationType != LocationType.Virtual;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tags.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The tags.</value>
|
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the remote trailers.
|
/// Gets or sets the remote trailers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -105,9 +98,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return base.GetDeletePaths();
|
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()
|
public GameInfo GetLookupInfo()
|
||||||
|
|
|
@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Game;
|
||||||
|
}
|
||||||
|
|
||||||
public GameSystemInfo GetLookupInfo()
|
public GameSystemInfo GetLookupInfo()
|
||||||
{
|
{
|
||||||
var id = GetItemLookupInfo<GameSystemInfo>();
|
var id = GetItemLookupInfo<GameSystemInfo>();
|
||||||
|
|
|
@ -16,6 +16,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
IEnumerable<string> PhysicalLocations { get; }
|
IEnumerable<string> PhysicalLocations { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ISupportsUserSpecificView
|
||||||
|
{
|
||||||
|
bool EnableUserSpecificView { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public static class CollectionFolderExtensions
|
public static class CollectionFolderExtensions
|
||||||
{
|
{
|
||||||
public static string GetViewType(this ICollectionFolder folder, User user)
|
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 MediaBrowser.Model.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string[] MediaTypes { get; set; }
|
public string[] MediaTypes { get; set; }
|
||||||
public string[] IncludeItemTypes { get; set; }
|
public string[] IncludeItemTypes { get; set; }
|
||||||
public string[] ExcludeItemTypes { get; set; }
|
public string[] ExcludeItemTypes { get; set; }
|
||||||
|
public string[] ExcludeTags { get; set; }
|
||||||
public string[] Genres { get; set; }
|
public string[] Genres { get; set; }
|
||||||
|
|
||||||
public bool? IsMissing { get; set; }
|
public bool? IsMissing { get; set; }
|
||||||
|
@ -69,12 +71,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public string[] Studios { get; set; }
|
public string[] Studios { get; set; }
|
||||||
public string[] StudioIds { get; set; }
|
public string[] StudioIds { get; set; }
|
||||||
|
public string[] GenreIds { get; set; }
|
||||||
public ImageType[] ImageTypes { get; set; }
|
public ImageType[] ImageTypes { get; set; }
|
||||||
public VideoType[] VideoTypes { get; set; }
|
public VideoType[] VideoTypes { get; set; }
|
||||||
|
public UnratedItem[] BlockUnratedItems { get; set; }
|
||||||
public int[] Years { get; set; }
|
public int[] Years { get; set; }
|
||||||
public string[] Tags { get; set; }
|
public string[] Tags { get; set; }
|
||||||
public string[] OfficialRatings { get; set; }
|
public string[] OfficialRatings { get; set; }
|
||||||
|
|
||||||
|
public DateTime? MinPremiereDate { get; set; }
|
||||||
public DateTime? MinStartDate { get; set; }
|
public DateTime? MinStartDate { get; set; }
|
||||||
public DateTime? MaxStartDate { get; set; }
|
public DateTime? MaxStartDate { get; set; }
|
||||||
public DateTime? MinEndDate { get; set; }
|
public DateTime? MinEndDate { get; set; }
|
||||||
|
@ -87,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public int? MinPlayers { get; set; }
|
public int? MinPlayers { get; set; }
|
||||||
public int? MaxPlayers { get; set; }
|
public int? MaxPlayers { get; set; }
|
||||||
|
public int? MinIndexNumber { get; set; }
|
||||||
public double? MinCriticRating { get; set; }
|
public double? MinCriticRating { get; set; }
|
||||||
public double? MinCommunityRating { get; set; }
|
public double? MinCommunityRating { get; set; }
|
||||||
|
|
||||||
|
@ -101,9 +107,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public LocationType? LocationType { get; set; }
|
public LocationType? LocationType { get; set; }
|
||||||
|
|
||||||
public Guid? ParentId { get; set; }
|
public Guid? ParentId { get; set; }
|
||||||
|
public string[] AncestorIds { get; set; }
|
||||||
|
public string[] TopParentIds { get; set; }
|
||||||
|
|
||||||
|
public LocationType[] ExcludeLocationTypes { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
|
BlockUnratedItems = new UnratedItem[] { };
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
OfficialRatings = new string[] { };
|
OfficialRatings = new string[] { };
|
||||||
SortBy = new string[] { };
|
SortBy = new string[] { };
|
||||||
|
@ -113,6 +124,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Genres = new string[] { };
|
Genres = new string[] { };
|
||||||
Studios = new string[] { };
|
Studios = new string[] { };
|
||||||
StudioIds = new string[] { };
|
StudioIds = new string[] { };
|
||||||
|
GenreIds = new string[] { };
|
||||||
ImageTypes = new ImageType[] { };
|
ImageTypes = new ImageType[] { };
|
||||||
VideoTypes = new VideoType[] { };
|
VideoTypes = new VideoType[] { };
|
||||||
Years = new int[] { };
|
Years = new int[] { };
|
||||||
|
@ -120,6 +132,29 @@ namespace MediaBrowser.Controller.Entities
|
||||||
PersonIds = new string[] { };
|
PersonIds = new string[] { };
|
||||||
ChannelIds = new string[] { };
|
ChannelIds = new string[] { };
|
||||||
ItemIds = 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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Movies
|
namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BoxSet
|
/// Class BoxSet
|
||||||
/// </summary>
|
/// </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; }
|
public List<Share> Shares { get; set; }
|
||||||
|
|
||||||
|
@ -65,6 +63,11 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Movie;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool IsPreSorted
|
public override bool IsPreSorted
|
||||||
{
|
{
|
||||||
|
@ -154,34 +157,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
return GetItemLookupInfo<BoxSetInfo>();
|
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)
|
public override bool IsVisible(User user)
|
||||||
{
|
{
|
||||||
var userId = user.Id.ToString("N");
|
var userId = user.Id.ToString("N");
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
|
|
||||||
// Must have a parent to have special features
|
// Must have a parent to have special features
|
||||||
// In other words, it must be part of the Parent/Child tree
|
// 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);
|
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -159,9 +159,9 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
return itemsChanged;
|
return itemsChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
return UnratedItem.Movie;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovieInfo GetLookupInfo()
|
public MovieInfo GetLookupInfo()
|
||||||
|
|
|
@ -56,9 +56,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
|
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()
|
public MusicVideoInfo GetLookupInfo()
|
||||||
|
|
|
@ -102,6 +102,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsAncestors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Photo : BaseItem, IHasTags, IHasTaglines
|
public class Photo : BaseItem, IHasTags, IHasTaglines
|
||||||
{
|
{
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
public List<string> Taglines { get; set; }
|
public List<string> Taglines { get; set; }
|
||||||
|
|
||||||
public Photo()
|
public Photo()
|
||||||
{
|
{
|
||||||
Tags = new List<string>();
|
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +49,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
get
|
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? Longitude { get; set; }
|
||||||
public double? Altitude { get; set; }
|
public double? Altitude { get; set; }
|
||||||
public int? IsoSpeedRating { 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
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class PhotoAlbum : Folder, IMetadataContainer
|
public class PhotoAlbum : Folder
|
||||||
{
|
{
|
||||||
|
[IgnoreDataMember]
|
||||||
public override bool SupportsLocalMetadata
|
public override bool SupportsLocalMetadata
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -32,31 +33,5 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
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>
|
/// </summary>
|
||||||
public class Studio : BaseItem, IItemByName, IHasTags
|
public class Studio : BaseItem, IItemByName, IHasTags
|
||||||
{
|
{
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
|
|
||||||
public Studio()
|
|
||||||
{
|
|
||||||
Tags = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Season ?? Parent;
|
return Season ?? GetParent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,19 +115,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return base.CreateUserDataKey();
|
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>
|
/// <summary>
|
||||||
/// This Episode's Series Instance
|
/// This Episode's Series Instance
|
||||||
/// </summary>
|
/// </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()
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
{
|
{
|
||||||
return new[] { Path };
|
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()
|
public EpisodeInfo GetLookupInfo()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using MoreLinq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
|
@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override BaseItem DisplayParent
|
public override BaseItem DisplayParent
|
||||||
{
|
{
|
||||||
get { return Series ?? Parent; }
|
get { return Series ?? GetParent(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Genre, Rating and Stuido will all be the same
|
// 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>
|
/// <summary>
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -234,6 +222,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Series;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string SeriesName
|
public string SeriesName
|
||||||
{
|
{
|
||||||
|
|
|
@ -333,6 +333,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Series);
|
return config.BlockUnratedItems.Contains(UnratedItem.Series);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.Series;
|
||||||
|
}
|
||||||
|
|
||||||
public SeriesInfo GetLookupInfo()
|
public SeriesInfo GetLookupInfo()
|
||||||
{
|
{
|
||||||
var info = GetItemLookupInfo<SeriesInfo>();
|
var info = GetItemLookupInfo<SeriesInfo>();
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// Local trailers are not part of children
|
// Local trailers are not part of children
|
||||||
return Parent == null;
|
return GetParent() == null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return base.CreateUserDataKey();
|
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()
|
public TrailerInfo GetLookupInfo()
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public static IUserManager UserManager { get; set; }
|
public static IUserManager UserManager { get; set; }
|
||||||
public static IXmlSerializer XmlSerializer { get; set; }
|
public static IXmlSerializer XmlSerializer { get; set; }
|
||||||
public bool EnableUserViews { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// From now on all user paths will be Id-based.
|
/// 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>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// 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>
|
/// <summary>
|
||||||
/// Get the children of this folder from the actual file system
|
/// Get the children of this folder from the actual file system
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren);
|
return base.GetNonCachedChildren(directoryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool BeforeMetadataRefresh()
|
public override bool BeforeMetadataRefresh()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public Guid DisplayParentId { get; set; }
|
public Guid DisplayParentId { get; set; }
|
||||||
|
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
|
|
||||||
public static ITVSeriesManager TVSeriesManager;
|
public static ITVSeriesManager TVSeriesManager;
|
||||||
public static IPlaylistManager PlaylistManager;
|
public static IPlaylistManager PlaylistManager;
|
||||||
|
|
||||||
|
@ -24,7 +25,26 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
return true;
|
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)
|
public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var parent = this as Folder;
|
var parent = this as Folder;
|
||||||
|
@ -81,16 +101,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetChildren(user, false);
|
return GetChildren(user, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsExcludedFromGrouping(Folder folder)
|
public static bool IsUserSpecific(Folder folder)
|
||||||
{
|
{
|
||||||
var standaloneTypes = new List<string>
|
var standaloneTypes = new List<string>
|
||||||
{
|
{
|
||||||
CollectionType.Books,
|
CollectionType.Playlists
|
||||||
CollectionType.HomeVideos,
|
|
||||||
CollectionType.Photos,
|
|
||||||
CollectionType.Playlists,
|
|
||||||
CollectionType.BoxSets,
|
|
||||||
CollectionType.MusicVideos
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var collectionFolder = folder as ICollectionFolder;
|
var collectionFolder = folder as ICollectionFolder;
|
||||||
|
@ -100,25 +115,63 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var supportsUserSpecific = folder as ISupportsUserSpecificView;
|
||||||
|
if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
|
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsUserSpecific(Folder folder)
|
public static bool IsEligibleForGrouping(Folder folder)
|
||||||
{
|
{
|
||||||
var standaloneTypes = new List<string>
|
var collectionFolder = folder as ICollectionFolder;
|
||||||
{
|
return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType);
|
||||||
CollectionType.Playlists,
|
}
|
||||||
|
|
||||||
|
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
|
CollectionType.BoxSets
|
||||||
};
|
};
|
||||||
|
|
||||||
var collectionFolder = folder as ICollectionFolder;
|
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
if (collectionFolder == null)
|
protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
return false;
|
return Task.FromResult(true);
|
||||||
}
|
|
||||||
|
|
||||||
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -120,59 +120,34 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
|
return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CollectionType.Photos:
|
||||||
case CollectionType.Books:
|
case CollectionType.Books:
|
||||||
case CollectionType.HomeVideos:
|
case CollectionType.HomeVideos:
|
||||||
|
case CollectionType.Games:
|
||||||
case CollectionType.MusicVideos:
|
case CollectionType.MusicVideos:
|
||||||
|
{
|
||||||
|
if (query.Recursive)
|
||||||
|
{
|
||||||
|
return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
|
||||||
|
}
|
||||||
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
|
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
|
||||||
|
}
|
||||||
|
|
||||||
case CollectionType.Folders:
|
case CollectionType.Folders:
|
||||||
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
|
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
|
||||||
|
|
||||||
case CollectionType.Games:
|
|
||||||
return await GetGameView(user, queryParent, query).ConfigureAwait(false);
|
|
||||||
|
|
||||||
case CollectionType.Playlists:
|
case CollectionType.Playlists:
|
||||||
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
|
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case CollectionType.BoxSets:
|
case CollectionType.BoxSets:
|
||||||
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
|
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case CollectionType.Photos:
|
|
||||||
return await GetPhotosView(queryParent, user, query).ConfigureAwait(false);
|
|
||||||
|
|
||||||
case CollectionType.TvShows:
|
case CollectionType.TvShows:
|
||||||
return await GetTvView(queryParent, user, query).ConfigureAwait(false);
|
return await GetTvView(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case CollectionType.Music:
|
|
||||||
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
|
|
||||||
|
|
||||||
case CollectionType.Movies:
|
case CollectionType.Movies:
|
||||||
return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false);
|
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:
|
case SpecialFolder.TvShowSeries:
|
||||||
return GetTvSeries(queryParent, user, query);
|
return GetTvSeries(queryParent, user, query);
|
||||||
|
|
||||||
|
@ -212,6 +187,21 @@ namespace MediaBrowser.Controller.Entities
|
||||||
case SpecialFolder.MovieCollections:
|
case SpecialFolder.MovieCollections:
|
||||||
return GetMovieCollections(queryParent, user, query);
|
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:
|
case SpecialFolder.MusicLatest:
|
||||||
return GetMusicLatest(queryParent, user, query);
|
return GetMusicLatest(queryParent, user, query);
|
||||||
|
|
||||||
|
@ -230,12 +220,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
case SpecialFolder.MusicSongs:
|
case SpecialFolder.MusicSongs:
|
||||||
return GetMusicSongs(queryParent, user, query);
|
return GetMusicSongs(queryParent, user, query);
|
||||||
|
|
||||||
case SpecialFolder.TvFavoriteEpisodes:
|
|
||||||
return GetFavoriteEpisodes(queryParent, user, query);
|
|
||||||
|
|
||||||
case SpecialFolder.TvFavoriteSeries:
|
|
||||||
return GetFavoriteSeries(queryParent, user, query);
|
|
||||||
|
|
||||||
case SpecialFolder.MusicFavorites:
|
case SpecialFolder.MusicFavorites:
|
||||||
return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false);
|
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)
|
private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.Recursive)
|
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.MusicPlaylists, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", 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.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.MusicSongs, "5", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", 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);
|
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)
|
private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.Recursive)
|
if (query.Recursive)
|
||||||
|
@ -480,24 +482,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return PostFilterAndSort(items, parent, null, query);
|
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)
|
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));
|
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query));
|
||||||
|
@ -582,19 +566,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetResult(collections, parent, query);
|
return GetResult(collections, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetPhotosView(Folder queryParent, User user, InternalItemsQuery query)
|
|
||||||
{
|
|
||||||
if (query.Recursive)
|
|
||||||
{
|
|
||||||
var mediaTypes = new[] { MediaType.Video, MediaType.Photo };
|
|
||||||
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Photos, string.Empty }, i => (i is PhotoAlbum || mediaTypes.Contains(i.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) && FilterItem(i, query));
|
|
||||||
|
|
||||||
return PostFilterAndSort(items, queryParent, null, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
|
private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.Recursive)
|
if (query.Recursive)
|
||||||
|
@ -617,54 +588,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetResult(list, parent, query);
|
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)
|
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
|
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
|
||||||
|
@ -745,49 +668,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetResult(items, queryParent, query);
|
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)
|
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
|
||||||
where T : BaseItem
|
where T : BaseItem
|
||||||
{
|
{
|
||||||
|
@ -1061,6 +941,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.GenreIds.Length > 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (request.VideoTypes.Length > 0)
|
if (request.VideoTypes.Length > 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1101,10 +986,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.MinIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<BaseItem> FilterVirtualEpisodes(
|
private static IEnumerable<BaseItem> FilterVirtualEpisodes(
|
||||||
IEnumerable<BaseItem> items,
|
IEnumerable<BaseItem> items,
|
||||||
bool? isMissing,
|
bool? isMissing,
|
||||||
bool? isVirtualUnaired,
|
bool? isVirtualUnaired,
|
||||||
|
@ -1374,7 +1264,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
if (query.IsInBoxSet.HasValue)
|
if (query.IsInBoxSet.HasValue)
|
||||||
{
|
{
|
||||||
var val = query.IsInBoxSet.Value;
|
var val = query.IsInBoxSet.Value;
|
||||||
if (item.Parents.OfType<BoxSet>().Any() != val)
|
if (item.GetParents().OfType<BoxSet>().Any() != val)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1657,6 +1547,16 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
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
|
// Apply year filter
|
||||||
if (query.Years.Length > 0)
|
if (query.Years.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -1779,6 +1679,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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1789,12 +1699,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return _libraryManager.RootFolder
|
return _libraryManager.RootFolder
|
||||||
.Children
|
.Children
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.Where(i => !UserView.IsExcludedFromGrouping(i));
|
.Where(UserView.IsEligibleForGrouping);
|
||||||
}
|
}
|
||||||
return user.RootFolder
|
return user.RootFolder
|
||||||
.GetChildren(user, true, true)
|
.GetChildren(user, true)
|
||||||
.OfType<Folder>()
|
.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)
|
private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
|
||||||
|
|
|
@ -185,12 +185,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public bool IsShortcut { get; set; }
|
public bool IsShortcut { get; set; }
|
||||||
public string ShortcutPath { 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>
|
/// <summary>
|
||||||
/// Gets or sets the video bit rate.
|
/// Gets or sets the video bit rate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -356,7 +350,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
// Must have a parent to have additional parts or alternate versions
|
// Must have a parent to have additional parts or alternate versions
|
||||||
// In other words, it must be part of the Parent/Child tree
|
// In other words, it must be part of the Parent/Child tree
|
||||||
// The additional parts won't have additional parts themselves
|
// The additional parts won't have additional parts themselves
|
||||||
if (LocationType == LocationType.FileSystem && Parent != null)
|
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
||||||
{
|
{
|
||||||
if (!IsStacked)
|
if (!IsStacked)
|
||||||
{
|
{
|
||||||
|
|
|
@ -337,7 +337,6 @@ namespace MediaBrowser.Controller.Library
|
||||||
string parentId,
|
string parentId,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
string uniqueId,
|
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -391,13 +390,11 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="parent">The parent.</param>
|
/// <param name="parent">The parent.</param>
|
||||||
/// <param name="viewType">Type of the view.</param>
|
/// <param name="viewType">Type of the view.</param>
|
||||||
/// <param name="sortName">Name of the sort.</param>
|
/// <param name="sortName">Name of the sort.</param>
|
||||||
/// <param name="uniqueId">The unique identifier.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<UserView>.</returns>
|
/// <returns>Task<UserView>.</returns>
|
||||||
Task<UserView> GetShadowView(BaseItem parent,
|
Task<UserView> GetShadowView(BaseItem parent,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
string uniqueId,
|
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -543,5 +540,29 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="imageIndex">Index of the image.</param>
|
/// <param name="imageIndex">Index of the image.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
|
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.
|
// Not officially supported but in some cases we can handle it.
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
item = parent.Parents.OfType<T>().FirstOrDefault();
|
item = parent.GetParents().OfType<T>().FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
return item != null;
|
return item != null;
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public bool IsLive { get; set; }
|
public bool IsLive { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsPremiere { get; set; }
|
public bool IsPremiere { get; set; }
|
||||||
public ProgramAudio? Audio { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// 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)
|
protected override string GetInternalMetadataPath(string basePath)
|
||||||
|
@ -140,5 +139,10 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsVisibleStandalone(User user)
|
||||||
|
{
|
||||||
|
return IsVisible(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
return GetClientTypeName() + "-" + Name;
|
return GetClientTypeName() + "-" + Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel);
|
return UnratedItem.LiveTvChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -40,10 +40,11 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the channel.
|
/// Gets or sets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the channel.</value>
|
/// <value>The name.</value>
|
||||||
public ChannelType ChannelType { get; set; }
|
[IgnoreDataMember]
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start date of the program, in UTC.
|
/// The start date of the program, in UTC.
|
||||||
|
@ -51,12 +52,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public DateTime StartDate { get; set; }
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the audio.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The audio.</value>
|
|
||||||
public ProgramAudio? Audio { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance is repeat.
|
/// Gets or sets a value indicating whether this instance is repeat.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -71,12 +66,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string EpisodeTitle { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance is movie.
|
/// Gets or sets a value indicating whether this instance is movie.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -153,14 +142,14 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
//[IgnoreDataMember]
|
||||||
public override string MediaType
|
//public override string MediaType
|
||||||
{
|
//{
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
|
// return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsAiring
|
public bool IsAiring
|
||||||
|
@ -189,9 +178,9 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
return "Program";
|
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)
|
protected override string GetInternalMetadataPath(string basePath)
|
||||||
|
@ -236,5 +225,14 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
return base.SupportsPeople;
|
return base.SupportsPeople;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsAncestors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public bool IsLive { get; set; }
|
public bool IsLive { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsPremiere { get; set; }
|
public bool IsPremiere { get; set; }
|
||||||
public ProgramAudio? Audio { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// 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)
|
protected override string GetInternalMetadataPath(string basePath)
|
||||||
|
@ -155,5 +154,10 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsVisibleStandalone(User user)
|
||||||
|
{
|
||||||
|
return IsVisible(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
@ -11,6 +12,11 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
{
|
||||||
|
return UnratedItem.LiveTvProgram;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool SupportsLocalMetadata
|
public override bool SupportsLocalMetadata
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -162,6 +162,7 @@
|
||||||
<Compile Include="Entities\IHasThemeMedia.cs" />
|
<Compile Include="Entities\IHasThemeMedia.cs" />
|
||||||
<Compile Include="Entities\IHasTrailers.cs" />
|
<Compile Include="Entities\IHasTrailers.cs" />
|
||||||
<Compile Include="Entities\IHasUserData.cs" />
|
<Compile Include="Entities\IHasUserData.cs" />
|
||||||
|
<Compile Include="Entities\IHiddenFromDisplay.cs" />
|
||||||
<Compile Include="Entities\IItemByName.cs" />
|
<Compile Include="Entities\IItemByName.cs" />
|
||||||
<Compile Include="Entities\ILibraryItem.cs" />
|
<Compile Include="Entities\ILibraryItem.cs" />
|
||||||
<Compile Include="Entities\ImageSourceInfo.cs" />
|
<Compile Include="Entities\ImageSourceInfo.cs" />
|
||||||
|
|
|
@ -176,6 +176,20 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>QueryResult<Tuple<Guid, System.String>>.</returns>
|
/// <returns>QueryResult<Tuple<Guid, System.String>>.</returns>
|
||||||
QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
|
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; }
|
public string PlaylistMediaType { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -10,24 +10,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
/// <value>The item identifier.</value>
|
/// <value>The item identifier.</value>
|
||||||
public Guid ItemId { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the date last metadata refresh.
|
/// Gets or sets the date last metadata refresh.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -40,22 +22,8 @@ namespace MediaBrowser.Controller.Providers
|
||||||
/// <value>The date last images refresh.</value>
|
/// <value>The date last images refresh.</value>
|
||||||
public DateTime? DateLastImagesRefresh { get; set; }
|
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 DateTime? ItemDateModified { get; set; }
|
||||||
|
|
||||||
public void AddStatus(string errorMessage)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(LastErrorMessage))
|
|
||||||
{
|
|
||||||
LastErrorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDirty { get; private set; }
|
public bool IsDirty { get; private set; }
|
||||||
|
|
||||||
public void SetDateLastMetadataRefresh(DateTime? date)
|
public void SetDateLastMetadataRefresh(DateTime? date)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Controller.Library;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Resolvers
|
namespace MediaBrowser.Controller.Resolvers
|
||||||
{
|
{
|
||||||
|
@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IResolverIgnoreRule
|
public interface IResolverIgnoreRule
|
||||||
{
|
{
|
||||||
bool ShouldIgnore(ItemResolveArgs args);
|
bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
private readonly IUserViewManager _userViewManager;
|
||||||
|
|
||||||
public ContentDirectory(IDlnaManager dlna,
|
public ContentDirectory(IDlnaManager dlna,
|
||||||
IUserDataManager userDataManager,
|
IUserDataManager userDataManager,
|
||||||
|
@ -34,7 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager)
|
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_dlna = dlna;
|
_dlna = dlna;
|
||||||
|
@ -46,6 +47,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
|
_userViewManager = userViewManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int SystemUpdateId
|
private int SystemUpdateId
|
||||||
|
@ -86,7 +88,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
_config,
|
_config,
|
||||||
_localization,
|
_localization,
|
||||||
_channelManager,
|
_channelManager,
|
||||||
_mediaSourceManager)
|
_mediaSourceManager,
|
||||||
|
_userViewManager)
|
||||||
.ProcessControlRequest(request);
|
.ProcessControlRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Model.Library;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.ContentDirectory
|
namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
{
|
{
|
||||||
|
@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly User _user;
|
private readonly User _user;
|
||||||
|
private readonly IUserViewManager _userViewManager;
|
||||||
|
|
||||||
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
|
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/";
|
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;
|
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)
|
: base(config, logger)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
@ -55,6 +57,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
_user = user;
|
_user = user;
|
||||||
_systemUpdateId = systemUpdateId;
|
_systemUpdateId = systemUpdateId;
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
|
_userViewManager = userViewManager;
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
|
@ -450,16 +453,32 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
sortOrders.Add(ItemSortBy.SortName);
|
sortOrders.Add(ItemSortBy.SortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryResult = await folder.GetItems(new InternalItemsQuery
|
QueryResult<BaseItem> queryResult;
|
||||||
{
|
|
||||||
Limit = limit,
|
|
||||||
StartIndex = startIndex,
|
|
||||||
SortBy = sortOrders.ToArray(),
|
|
||||||
SortOrder = sort.SortOrder,
|
|
||||||
User = user,
|
|
||||||
Filter = FilterUnsupportedContent
|
|
||||||
|
|
||||||
}).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();
|
var options = _config.GetDlnaConfiguration();
|
||||||
|
|
||||||
|
@ -481,23 +500,17 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
|
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
|
var serverItems = itemsResult.Items.Select(i => new ServerItem
|
||||||
.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
|
|
||||||
{
|
{
|
||||||
Item = i,
|
Item = i,
|
||||||
StubType = null
|
StubType = null
|
||||||
|
@ -506,7 +519,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
|
|
||||||
return new QueryResult<ServerItem>
|
return new QueryResult<ServerItem>
|
||||||
{
|
{
|
||||||
TotalRecordCount = serverItems.Length,
|
TotalRecordCount = itemsResult.TotalRecordCount,
|
||||||
Items = serverItems
|
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)
|
if (item != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
|
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var inputFormat = subtitle.Item2;
|
||||||
|
|
||||||
|
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
|
||||||
|
{
|
||||||
|
return subtitle.Item1;
|
||||||
|
}
|
||||||
|
|
||||||
using (var stream = subtitle.Item1)
|
using (var stream = subtitle.Item1)
|
||||||
{
|
{
|
||||||
var inputFormat = subtitle.Item2;
|
|
||||||
|
|
||||||
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
|
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISubtitleWriter GetWriter(string format)
|
private ISubtitleWriter TryGetWriter(string format)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(format))
|
if (string.IsNullOrEmpty(format))
|
||||||
{
|
{
|
||||||
|
@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
return new TtmlWriter();
|
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);
|
throw new ArgumentException("Unsupported format: " + format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1413,6 +1413,13 @@ namespace MediaBrowser.Model.ApiClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<System.Int32>.</returns>
|
/// <returns>Task<System.Int32>.</returns>
|
||||||
Task<int> GetSupportedBitrate(CancellationToken cancellationToken);
|
Task<int> DetectMaxBitrate(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the end point information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>System.Threading.Tasks.Task<MediaBrowser.Model.Net.EndPointInfo>.</returns>
|
||||||
|
Task<EndPointInfo> GetEndPointInfo(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,16 +11,19 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public bool EnableIntrosParentalControl { get; set; }
|
public bool EnableIntrosParentalControl { get; set; }
|
||||||
public bool EnableIntrosFromSimilarMovies { get; set; }
|
public bool EnableIntrosFromSimilarMovies { get; set; }
|
||||||
public string CustomIntroPath { get; set; }
|
public string CustomIntroPath { get; set; }
|
||||||
|
public string MediaInfoIntroPath { get; set; }
|
||||||
public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
|
public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
|
||||||
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
|
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
|
||||||
|
|
||||||
public int TrailerLimit { get; set; }
|
public int TrailerLimit { get; set; }
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
|
||||||
public CinemaModeConfiguration()
|
public CinemaModeConfiguration()
|
||||||
{
|
{
|
||||||
EnableIntrosParentalControl = true;
|
EnableIntrosParentalControl = true;
|
||||||
EnableIntrosFromSimilarMovies = true;
|
EnableIntrosFromSimilarMovies = true;
|
||||||
TrailerLimit = 2;
|
TrailerLimit = 2;
|
||||||
|
Tags = new[] { "thx" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,24 +92,6 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
|
||||||
public bool EnableLocalizedGuids { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the preferred metadata language.
|
/// Gets or sets the preferred metadata language.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -181,7 +163,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public string DashboardSourcePath { get; set; }
|
public string DashboardSourcePath { get; set; }
|
||||||
|
|
||||||
public bool MergeMetadataAndImagesByName { get; set; }
|
public bool MergeMetadataAndImagesByName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image saving convention.
|
/// Gets or sets the image saving convention.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -220,18 +202,18 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
public bool EnableWindowsShortcuts { get; set; }
|
public bool EnableWindowsShortcuts { get; set; }
|
||||||
|
|
||||||
public bool EnableVideoFrameByFrameAnalysis { get; set; }
|
|
||||||
|
|
||||||
public bool EnableDateLastRefresh { get; set; }
|
public bool EnableDateLastRefresh { get; set; }
|
||||||
|
|
||||||
public string[] Migrations { get; set; }
|
public string[] Migrations { get; set; }
|
||||||
|
|
||||||
|
public int MigrationVersion { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ServerConfiguration()
|
public ServerConfiguration()
|
||||||
{
|
{
|
||||||
Migrations = new string[] {};
|
Migrations = new string[] { };
|
||||||
|
|
||||||
ImageSavingConvention = ImageSavingConvention.Compatible;
|
ImageSavingConvention = ImageSavingConvention.Compatible;
|
||||||
PublicPort = 8096;
|
PublicPort = 8096;
|
||||||
|
@ -576,7 +558,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
Type = ImageType.Thumb
|
Type = ImageType.Thumb
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DisabledMetadataFetchers = new []{ "TheMovieDb" }
|
DisabledMetadataFetchers = new []{ "The Open Movie Database", "TheMovieDb" }
|
||||||
},
|
},
|
||||||
|
|
||||||
new MetadataOptions(0, 1280)
|
new MetadataOptions(0, 1280)
|
||||||
|
@ -597,6 +579,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
Type = ImageType.Primary
|
Type = ImageType.Primary
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
DisabledMetadataFetchers = new []{ "The Open Movie Database" },
|
||||||
DisabledImageFetchers = new []{ "TheMovieDb" }
|
DisabledImageFetchers = new []{ "TheMovieDb" }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,11 +47,11 @@ namespace MediaBrowser.Providers.BoxSets
|
||||||
|
|
||||||
if (mergeMetadataSettings)
|
if (mergeMetadataSettings)
|
||||||
{
|
{
|
||||||
var list = sourceItem.LinkedChildren.Where(i => i.Type != LinkedChildType.Manual).ToList();
|
// Retain shortcut children
|
||||||
|
var linkedChildren = sourceItem.LinkedChildren.ToList();
|
||||||
|
linkedChildren.AddRange(sourceItem.LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut));
|
||||||
|
|
||||||
list.AddRange(targetItem.LinkedChildren.Where(i => i.Type == LinkedChildType.Manual));
|
targetItem.LinkedChildren = linkedChildren;
|
||||||
|
|
||||||
targetItem.LinkedChildren = list;
|
|
||||||
targetItem.Shares = sourceItem.Shares;
|
targetItem.Shares = sourceItem.Shares;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1022,7 +1022,7 @@ namespace MediaBrowser.Providers.Manager
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var musicArtists = albums
|
var musicArtists = albums
|
||||||
.Select(i => i.Parent)
|
.Select(i => i.GetParent())
|
||||||
.OfType<MusicArtist>()
|
.OfType<MusicArtist>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@
|
||||||
<Compile Include="TV\MovieDbSeasonProvider.cs" />
|
<Compile Include="TV\MovieDbSeasonProvider.cs" />
|
||||||
<Compile Include="TV\MovieDbSeriesImageProvider.cs" />
|
<Compile Include="TV\MovieDbSeriesImageProvider.cs" />
|
||||||
<Compile Include="TV\MovieDbSeriesProvider.cs" />
|
<Compile Include="TV\MovieDbSeriesProvider.cs" />
|
||||||
|
<Compile Include="TV\OmdbEpisodeProvider.cs" />
|
||||||
<Compile Include="TV\SeriesMetadataService.cs" />
|
<Compile Include="TV\SeriesMetadataService.cs" />
|
||||||
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
|
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
|
||||||
<Compile Include="People\TvdbPersonImageProvider.cs" />
|
<Compile Include="People\TvdbPersonImageProvider.cs" />
|
||||||
|
|
|
@ -223,7 +223,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
FetchEmbeddedInfo(video, mediaInfo, options);
|
FetchEmbeddedInfo(video, mediaInfo, options);
|
||||||
await FetchPeople(video, mediaInfo, options).ConfigureAwait(false);
|
await FetchPeople(video, mediaInfo, options).ConfigureAwait(false);
|
||||||
|
|
||||||
video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
|
video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1260);
|
||||||
|
|
||||||
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
|
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the http requests since we know it's not currently supported
|
// Save the http requests since we know it's not currently supported
|
||||||
if (item is Series || item is Season || item is Episode)
|
if (item is Season || item is Episode)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,12 +65,18 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
private async Task<IEnumerable<RemoteSearchResult>> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken)
|
private async Task<IEnumerable<RemoteSearchResult>> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool isSearch = false;
|
bool isSearch = false;
|
||||||
|
var episodeSearchInfo = searchInfo as EpisodeInfo;
|
||||||
|
|
||||||
var list = new List<RemoteSearchResult>();
|
var list = new List<RemoteSearchResult>();
|
||||||
|
|
||||||
var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
|
var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
|
||||||
var url = "http://www.omdbapi.com/?plot=short&r=json";
|
var url = "http://www.omdbapi.com/?plot=full&r=json";
|
||||||
|
if (type == "episode" && episodeSearchInfo != null)
|
||||||
|
{
|
||||||
|
episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var name = searchInfo.Name;
|
var name = searchInfo.Name;
|
||||||
var year = searchInfo.Year;
|
var year = searchInfo.Year;
|
||||||
|
@ -107,6 +113,18 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
url += "&i=" + imdbId;
|
url += "&i=" + imdbId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == "episode")
|
||||||
|
{
|
||||||
|
if (searchInfo.IndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
url += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
|
||||||
|
}
|
||||||
|
if (searchInfo.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
url += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using (var stream = await _httpClient.Get(new HttpRequestOptions
|
using (var stream = await _httpClient.Get(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
|
@ -136,10 +154,20 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
|
|
||||||
foreach (var result in resultList)
|
foreach (var result in resultList)
|
||||||
{
|
{
|
||||||
var item = new RemoteSearchResult();
|
var item = new RemoteSearchResult
|
||||||
|
{
|
||||||
|
IndexNumber = searchInfo.IndexNumber,
|
||||||
|
Name = result.Title,
|
||||||
|
ParentIndexNumber = searchInfo.ParentIndexNumber,
|
||||||
|
ProviderIds = searchInfo.ProviderIds,
|
||||||
|
SearchProviderName = Name
|
||||||
|
};
|
||||||
|
|
||||||
|
if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
|
||||||
|
{
|
||||||
|
item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
|
||||||
|
}
|
||||||
|
|
||||||
item.SearchProviderName = Name;
|
|
||||||
item.Name = result.Title;
|
|
||||||
item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
|
item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
|
||||||
|
|
||||||
int parsedYear;
|
int parsedYear;
|
||||||
|
@ -149,6 +177,13 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
item.ProductionYear = parsedYear;
|
item.ProductionYear = parsedYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DateTime released;
|
||||||
|
if (!string.IsNullOrEmpty(result.Released)
|
||||||
|
&& DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out released))
|
||||||
|
{
|
||||||
|
item.PremiereDate = released;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
item.ImageUrl = result.Poster;
|
item.ImageUrl = result.Poster;
|
||||||
|
@ -279,6 +314,8 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
public string Year { get; set; }
|
public string Year { get; set; }
|
||||||
public string Rated { get; set; }
|
public string Rated { get; set; }
|
||||||
public string Released { get; set; }
|
public string Released { get; set; }
|
||||||
|
public string Season { get; set; }
|
||||||
|
public string Episode { get; set; }
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
public string Genre { get; set; }
|
public string Genre { get; set; }
|
||||||
public string Director { get; set; }
|
public string Director { get; set; }
|
||||||
|
@ -293,6 +330,7 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
public string imdbRating { get; set; }
|
public string imdbRating { get; set; }
|
||||||
public string imdbVotes { get; set; }
|
public string imdbVotes { get; set; }
|
||||||
public string imdbID { get; set; }
|
public string imdbID { get; set; }
|
||||||
|
public string seriesID { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
public string Response { get; set; }
|
public string Response { get; set; }
|
||||||
}
|
}
|
||||||
|
|
89
MediaBrowser.Providers/TV/OmdbEpisodeProvider.cs
Normal file
89
MediaBrowser.Providers/TV/OmdbEpisodeProvider.cs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Providers.Omdb;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Providers.TV
|
||||||
|
{
|
||||||
|
class OmdbEpisodeProvider :
|
||||||
|
IRemoteMetadataProvider<Episode, EpisodeInfo>,
|
||||||
|
IHasOrder
|
||||||
|
{
|
||||||
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
private OmdbItemProvider _itemProvider;
|
||||||
|
|
||||||
|
public OmdbEpisodeProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger, ILibraryManager libraryManager)
|
||||||
|
{
|
||||||
|
_jsonSerializer = jsonSerializer;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
_itemProvider = new OmdbItemProvider(jsonSerializer, httpClient, logger, libraryManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _itemProvider.GetSearchResults(searchInfo, "episode", cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = new MetadataResult<Episode>
|
||||||
|
{
|
||||||
|
Item = new Episode()
|
||||||
|
};
|
||||||
|
|
||||||
|
var imdbId = info.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
imdbId = await GetEpisodeImdbId(info, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(imdbId))
|
||||||
|
{
|
||||||
|
result.Item.SetProviderId(MetadataProviders.Imdb, imdbId);
|
||||||
|
result.HasMetadata = true;
|
||||||
|
|
||||||
|
await new OmdbProvider(_jsonSerializer, _httpClient).Fetch(result.Item, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetEpisodeImdbId(EpisodeInfo info, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
|
||||||
|
var first = results.FirstOrDefault();
|
||||||
|
return first == null ? null : first.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// After TheTvDb
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "The Open Movie Database"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _itemProvider.GetImageResponse(url, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -96,6 +96,11 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
.OrderBy(i => i.Name);
|
.OrderBy(i => i.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> GetInstalledChannelIds()
|
||||||
|
{
|
||||||
|
return GetAllChannels().Select(i => GetInternalChannelId(i.Name));
|
||||||
|
}
|
||||||
|
|
||||||
public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
|
public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = string.IsNullOrWhiteSpace(query.UserId)
|
var user = string.IsNullOrWhiteSpace(query.UserId)
|
||||||
|
@ -402,25 +407,15 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
|
private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var parentFolder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false);
|
||||||
|
var parentFolderId = parentFolder.Id;
|
||||||
|
|
||||||
var id = GetInternalChannelId(channelInfo.Name);
|
var id = GetInternalChannelId(channelInfo.Name);
|
||||||
|
|
||||||
var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
|
var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
|
||||||
|
|
||||||
var isNew = false;
|
var isNew = false;
|
||||||
|
var forceUpdate = false;
|
||||||
if (!_fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
_logger.Debug("Creating directory {0}", path);
|
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(path);
|
|
||||||
|
|
||||||
if (!_fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
throw new IOException("Path not created: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
isNew = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = _libraryManager.GetItemById(id) as Channel;
|
var item = _libraryManager.GetItemById(id) as Channel;
|
||||||
var channelId = channelInfo.Name.GetMD5().ToString("N");
|
var channelId = channelInfo.Name.GetMD5().ToString("N");
|
||||||
|
@ -432,18 +427,29 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
Name = channelInfo.Name,
|
Name = channelInfo.Name,
|
||||||
Id = id,
|
Id = id,
|
||||||
DateCreated = _fileSystem.GetCreationTimeUtc(path),
|
DateCreated = _fileSystem.GetCreationTimeUtc(path),
|
||||||
DateModified = _fileSystem.GetLastWriteTimeUtc(path),
|
DateModified = _fileSystem.GetLastWriteTimeUtc(path)
|
||||||
Path = path,
|
|
||||||
ChannelId = channelId
|
|
||||||
};
|
};
|
||||||
|
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
|
item.Path = path;
|
||||||
|
|
||||||
|
if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
forceUpdate = true;
|
||||||
|
}
|
||||||
|
item.ChannelId = channelId;
|
||||||
|
|
||||||
|
if (item.ParentId != parentFolderId)
|
||||||
|
{
|
||||||
|
forceUpdate = true;
|
||||||
|
}
|
||||||
|
item.ParentId = parentFolderId;
|
||||||
|
|
||||||
item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
|
item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
|
||||||
item.Overview = channelInfo.Description;
|
item.Overview = channelInfo.Description;
|
||||||
|
@ -453,13 +459,17 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
item.Name = channelInfo.Name;
|
item.Name = channelInfo.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
|
if (isNew)
|
||||||
{
|
{
|
||||||
ForceSave = isNew
|
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}, cancellationToken);
|
else if (forceUpdate)
|
||||||
|
{
|
||||||
|
await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,6 +1229,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
BaseItem item;
|
BaseItem item;
|
||||||
bool isNew;
|
bool isNew;
|
||||||
|
bool forceUpdate = false;
|
||||||
|
|
||||||
if (info.Type == ChannelItemType.Folder)
|
if (info.Type == ChannelItemType.Folder)
|
||||||
{
|
{
|
||||||
|
@ -1248,25 +1259,26 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
item.ProductionYear = info.ProductionYear;
|
item.ProductionYear = info.ProductionYear;
|
||||||
item.ProviderIds = info.ProviderIds;
|
item.ProviderIds = info.ProviderIds;
|
||||||
item.OfficialRating = info.OfficialRating;
|
item.OfficialRating = info.OfficialRating;
|
||||||
|
|
||||||
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
|
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
|
||||||
|
item.Tags = info.Tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
var channelItem = (IChannelItem)item;
|
var channelItem = (IChannelItem)item;
|
||||||
|
|
||||||
channelItem.ChannelId = internalChannelId.ToString("N");
|
channelItem.ChannelId = internalChannelId.ToString("N");
|
||||||
|
|
||||||
|
if (item.ParentId != internalChannelId)
|
||||||
|
{
|
||||||
|
forceUpdate = true;
|
||||||
|
}
|
||||||
|
item.ParentId = internalChannelId;
|
||||||
|
|
||||||
if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
isNew = true;
|
forceUpdate = true;
|
||||||
}
|
}
|
||||||
channelItem.ExternalId = info.Id;
|
channelItem.ExternalId = info.Id;
|
||||||
|
|
||||||
if (isNew)
|
|
||||||
{
|
|
||||||
channelItem.Tags = info.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
var channelMediaItem = item as IChannelMediaItem;
|
var channelMediaItem = item as IChannelMediaItem;
|
||||||
|
|
||||||
if (channelMediaItem != null)
|
if (channelMediaItem != null)
|
||||||
|
@ -1294,6 +1306,10 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
|
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (forceUpdate)
|
||||||
|
{
|
||||||
|
await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,15 +123,15 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
private async Task CleanDatabase(CancellationToken cancellationToken)
|
private async Task CleanDatabase(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var allChannels = await _channelManager.GetChannelsInternal(new ChannelQuery { }, cancellationToken);
|
var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
|
||||||
|
|
||||||
var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Channel).Name }
|
IncludeItemTypes = new[] { typeof(Channel).Name }
|
||||||
});
|
});
|
||||||
|
|
||||||
var invalidIds = allIds
|
var invalidIds = databaseIds
|
||||||
.Except(allChannels.Items.Select(i => i.Id).ToList())
|
.Except(installedChannelIds)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var id in invalidIds)
|
foreach (var id in invalidIds)
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
return subItem;
|
return subItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = subItem.Parent;
|
var parent = subItem.GetParent();
|
||||||
|
|
||||||
if (parent != null && parent.HasImage(ImageType.Primary))
|
if (parent != null && parent.HasImage(ImageType.Primary))
|
||||||
{
|
{
|
||||||
|
@ -78,24 +78,9 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
return Task.FromResult(GetFinalItems(items, 2));
|
return Task.FromResult(GetFinalItems(items, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
|
protected override Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
|
||||||
{
|
{
|
||||||
var image = itemsWithImages
|
return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary);
|
||||||
.Where(i => i.HasImage(ImageType.Primary) && i.GetImageInfo(ImageType.Primary, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(ImageType.Primary)))
|
|
||||||
.Select(i => i.GetImagePath(ImageType.Primary))
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(image))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ext = Path.GetExtension(image);
|
|
||||||
|
|
||||||
var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext);
|
|
||||||
File.Copy(image, outputPath);
|
|
||||||
|
|
||||||
return outputPath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
public Folder GetCollectionsFolder(string userId)
|
public Folder GetCollectionsFolder(string userId)
|
||||||
{
|
{
|
||||||
return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>()
|
return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>()
|
||||||
|
.FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType<ManualCollectionsFolder>()
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Collections
|
namespace MediaBrowser.Server.Implementations.Collections
|
||||||
{
|
{
|
||||||
public class ManualCollectionsFolder : BasePluginFolder
|
public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay
|
||||||
{
|
{
|
||||||
public ManualCollectionsFolder()
|
public ManualCollectionsFolder()
|
||||||
{
|
{
|
||||||
|
@ -11,11 +11,6 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
DisplayMediaType = "CollectionFolder";
|
DisplayMediaType = "CollectionFolder";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsVisible(User user)
|
|
||||||
{
|
|
||||||
return base.IsVisible(user) && GetChildren(user, false).Any();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsHidden
|
public override bool IsHidden
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -24,7 +19,7 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsHiddenFromUser(User user)
|
public bool IsHiddenFromUser(User user)
|
||||||
{
|
{
|
||||||
return !user.Configuration.DisplayCollectionsView;
|
return !user.Configuration.DisplayCollectionsView;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Collections
|
||||||
|
|
||||||
public override string GetClientTypeName()
|
public override string GetClientTypeName()
|
||||||
{
|
{
|
||||||
return typeof (CollectionFolder).Name;
|
return typeof(CollectionFolder).Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -163,12 +163,36 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||||
ValidateItemByNamePath(newConfig);
|
ValidateItemByNamePath(newConfig);
|
||||||
ValidatePathSubstitutions(newConfig);
|
ValidatePathSubstitutions(newConfig);
|
||||||
ValidateMetadataPath(newConfig);
|
ValidateMetadataPath(newConfig);
|
||||||
|
ValidateSslCertificate(newConfig);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
|
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
|
||||||
|
|
||||||
base.ReplaceConfiguration(newConfiguration);
|
base.ReplaceConfiguration(newConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the SSL certificate.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newConfig">The new configuration.</param>
|
||||||
|
/// <exception cref="System.IO.DirectoryNotFoundException"></exception>
|
||||||
|
private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
|
||||||
|
{
|
||||||
|
var serverConfig = (ServerConfiguration)newConfig;
|
||||||
|
|
||||||
|
var newPath = serverConfig.CertificatePath;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(newPath)
|
||||||
|
&& !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!FileSystem.FileExists(newPath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ValidatePathSubstitutions(ServerConfiguration newConfig)
|
private void ValidatePathSubstitutions(ServerConfiguration newConfig)
|
||||||
{
|
{
|
||||||
foreach (var map in newConfig.PathSubstitutions)
|
foreach (var map in newConfig.PathSubstitutions)
|
||||||
|
|
|
@ -3,12 +3,15 @@ using MediaBrowser.Controller.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Controller.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Devices
|
namespace MediaBrowser.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
public class CameraUploadsFolder : BasePluginFolder
|
public class CameraUploadsFolder : BasePluginFolder, ISupportsUserSpecificView
|
||||||
{
|
{
|
||||||
public CameraUploadsFolder()
|
public CameraUploadsFolder()
|
||||||
{
|
{
|
||||||
|
@ -21,22 +24,8 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetChildren(user, true).Any() &&
|
|
||||||
base.IsVisible(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsHidden
|
return base.IsVisible(user) && HasChildren();
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return base.IsHidden || !Children.Any();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsHiddenFromUser(User user)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string CollectionType
|
public override string CollectionType
|
||||||
|
@ -48,6 +37,29 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
return typeof(CollectionFolder).Name;
|
return typeof(CollectionFolder).Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool? _hasChildren;
|
||||||
|
private bool HasChildren()
|
||||||
|
{
|
||||||
|
if (!_hasChildren.HasValue)
|
||||||
|
{
|
||||||
|
_hasChildren = LibraryManager.GetItemIds(new InternalItemsQuery { ParentId = Id }).Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _hasChildren.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
|
||||||
|
{
|
||||||
|
_hasChildren = null;
|
||||||
|
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool EnableUserSpecificView
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CameraUploadsDynamicFolder : IVirtualFolderCreator
|
public class CameraUploadsDynamicFolder : IVirtualFolderCreator
|
||||||
|
@ -65,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
|
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(path);
|
_fileSystem.CreateDirectory(path);
|
||||||
|
|
||||||
return new CameraUploadsFolder
|
return new CameraUploadsFolder
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Events;
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
@ -18,6 +17,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Devices
|
namespace MediaBrowser.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILibraryMonitor _libraryMonitor;
|
private readonly ILibraryMonitor _libraryMonitor;
|
||||||
private readonly IConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly INetworkManager _network;
|
private readonly INetworkManager _network;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated;
|
public event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated;
|
||||||
|
|
||||||
public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config, ILogger logger, INetworkManager network)
|
public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -187,11 +187,6 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetUploadPath(string deviceId)
|
|
||||||
{
|
|
||||||
return GetUploadPath(GetDevice(deviceId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetUploadPath(DeviceInfo device)
|
private string GetUploadPath(DeviceInfo device)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
|
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
|
||||||
|
@ -205,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
return config.CameraUploadPath;
|
return config.CameraUploadPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads");
|
var path = DefaultCameraUploadsPath;
|
||||||
|
|
||||||
if (config.EnableCameraUploadSubfolders)
|
if (config.EnableCameraUploadSubfolders)
|
||||||
{
|
{
|
||||||
|
@ -215,6 +210,11 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string DefaultCameraUploadsPath
|
||||||
|
{
|
||||||
|
get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
|
||||||
|
}
|
||||||
|
|
||||||
public async Task UpdateDeviceInfo(string id, DeviceOptions options)
|
public async Task UpdateDeviceInfo(string id, DeviceOptions options)
|
||||||
{
|
{
|
||||||
var device = GetDevice(id);
|
var device = GetDevice(id);
|
||||||
|
|
|
@ -163,16 +163,11 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
|
|
||||||
if (person != null)
|
if (person != null)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItems(new InternalItemsQuery
|
var items = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Person = byName.Name
|
Person = byName.Name
|
||||||
|
|
||||||
}).Items;
|
}, new string[] { });
|
||||||
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
return items.Where(i => i.IsVisibleStandalone(user)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return items.ToList();
|
return items.ToList();
|
||||||
}
|
}
|
||||||
|
@ -361,6 +356,8 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
var collectionFolder = item as ICollectionFolder;
|
var collectionFolder = item as ICollectionFolder;
|
||||||
if (collectionFolder != null)
|
if (collectionFolder != null)
|
||||||
{
|
{
|
||||||
|
dto.OriginalCollectionType = collectionFolder.CollectionType;
|
||||||
|
|
||||||
dto.CollectionType = user == null ?
|
dto.CollectionType = user == null ?
|
||||||
collectionFolder.CollectionType :
|
collectionFolder.CollectionType :
|
||||||
collectionFolder.GetViewType(user);
|
collectionFolder.GetViewType(user);
|
||||||
|
@ -468,13 +465,15 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
|
|
||||||
var folder = (Folder)item;
|
var folder = (Folder)item;
|
||||||
|
|
||||||
dto.ChildCount = GetChildCount(folder, user);
|
if (!(folder is IChannelItem) && !(folder is Channel))
|
||||||
|
|
||||||
// These are just far too slow.
|
|
||||||
// TODO: Disable for CollectionFolder
|
|
||||||
if (!(folder is UserRootFolder) && !(folder is UserView))
|
|
||||||
{
|
{
|
||||||
SetSpecialCounts(folder, user, dto, fields, syncProgress);
|
dto.ChildCount = GetChildCount(folder, user);
|
||||||
|
|
||||||
|
// These are just far too slow.
|
||||||
|
if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is ICollectionFolder))
|
||||||
|
{
|
||||||
|
SetSpecialCounts(folder, user, dto, fields, syncProgress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
|
dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
|
||||||
|
@ -815,7 +814,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
private BaseItem GetParentBackdropItem(BaseItem item, BaseItem owner)
|
private BaseItem GetParentBackdropItem(BaseItem item, BaseItem owner)
|
||||||
{
|
{
|
||||||
var parent = item.Parent ?? owner;
|
var parent = item.GetParent() ?? owner;
|
||||||
|
|
||||||
while (parent != null)
|
while (parent != null)
|
||||||
{
|
{
|
||||||
|
@ -824,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = parent.Parent;
|
parent = parent.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -839,7 +838,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
private BaseItem GetParentImageItem(BaseItem item, ImageType type, BaseItem owner)
|
private BaseItem GetParentImageItem(BaseItem item, ImageType type, BaseItem owner)
|
||||||
{
|
{
|
||||||
var parent = item.Parent ?? owner;
|
var parent = item.GetParent() ?? owner;
|
||||||
|
|
||||||
while (parent != null)
|
while (parent != null)
|
||||||
{
|
{
|
||||||
|
@ -848,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = parent.Parent;
|
parent = parent.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1042,7 +1041,11 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
dto.IsFolder = item.IsFolder;
|
dto.IsFolder = item.IsFolder;
|
||||||
dto.MediaType = item.MediaType;
|
dto.MediaType = item.MediaType;
|
||||||
dto.LocationType = item.LocationType;
|
dto.LocationType = item.LocationType;
|
||||||
dto.IsHD = item.IsHD;
|
if (item.IsHD.HasValue && item.IsHD.Value)
|
||||||
|
{
|
||||||
|
dto.IsHD = item.IsHD;
|
||||||
|
}
|
||||||
|
dto.Audio = item.Audio;
|
||||||
|
|
||||||
dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode;
|
dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode;
|
||||||
dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage;
|
dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage;
|
||||||
|
@ -1209,15 +1212,15 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
dto.VoteCount = item.VoteCount;
|
dto.VoteCount = item.VoteCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IsFolder)
|
//if (item.IsFolder)
|
||||||
{
|
//{
|
||||||
var folder = (Folder)item;
|
// var folder = (Folder)item;
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.IndexOptions))
|
// if (fields.Contains(ItemFields.IndexOptions))
|
||||||
{
|
// {
|
||||||
dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
|
// dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
var supportsPlaceHolders = item as ISupportsPlaceHolders;
|
var supportsPlaceHolders = item as ISupportsPlaceHolders;
|
||||||
if (supportsPlaceHolders != null)
|
if (supportsPlaceHolders != null)
|
||||||
|
@ -1520,7 +1523,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.ChannelId = item.ChannelId;
|
dto.ChannelId = item.ChannelId;
|
||||||
|
|
||||||
var channelItem = item as IChannelItem;
|
var channelItem = item as IChannelItem;
|
||||||
if (channelItem != null)
|
if (channelItem != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
// Go up one level for indicators
|
// Go up one level for indicators
|
||||||
if (baseItem != null)
|
if (baseItem != null)
|
||||||
{
|
{
|
||||||
var parent = baseItem.Parent;
|
var parent = baseItem.GetParent();
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -268,13 +268,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
|
|
||||||
private bool EnableLogging(string url)
|
private bool EnableLogging(string url)
|
||||||
{
|
{
|
||||||
var parts = url.Split(new[] { '?' }, 2);
|
var extension = GetExtension(url);
|
||||||
|
|
||||||
var extension = Path.GetExtension(parts[0]);
|
|
||||||
|
|
||||||
return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension);
|
return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetExtension(string url)
|
||||||
|
{
|
||||||
|
var parts = url.Split(new[] { '?' }, 2);
|
||||||
|
|
||||||
|
return Path.GetExtension(parts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable method that can be used to implement a custom hnandler
|
/// Overridable method that can be used to implement a custom hnandler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -339,6 +344,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
{
|
{
|
||||||
httpRes.Write(GlobalResponse);
|
httpRes.Write(GlobalResponse);
|
||||||
httpRes.ContentType = "text/plain";
|
httpRes.ContentType = "text/plain";
|
||||||
|
|
||||||
|
if (!string.Equals(GetExtension(urlString), "html", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
httpRes.StatusCode = 503;
|
||||||
|
}
|
||||||
|
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
||||||
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
|
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item.Parent is AggregateFolder)
|
if (e.Item.GetParent() is AggregateFolder)
|
||||||
{
|
{
|
||||||
StopWatchingPath(e.Item.Path);
|
StopWatchingPath(e.Item.Path);
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
||||||
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
|
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item.Parent is AggregateFolder)
|
if (e.Item.GetParent() is AggregateFolder)
|
||||||
{
|
{
|
||||||
StartWatchingPath(e.Item.Path);
|
StartWatchingPath(e.Item.Path);
|
||||||
}
|
}
|
||||||
|
@ -542,9 +542,16 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In order to determine if the file is being written to, we have to request write access
|
||||||
|
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
|
||||||
|
// So we'll take a best guess about our access level
|
||||||
|
var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
|
||||||
|
? FileAccess.ReadWrite
|
||||||
|
: FileAccess.Read;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
|
using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite))
|
||||||
{
|
{
|
||||||
if (_updateTimer != null)
|
if (_updateTimer != null)
|
||||||
{
|
{
|
||||||
|
@ -661,7 +668,7 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||||
// If the item has been deleted find the first valid parent that still exists
|
// If the item has been deleted find the first valid parent that still exists
|
||||||
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
|
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
|
||||||
{
|
{
|
||||||
item = item.Parent;
|
item = item.GetParent();
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,13 +78,11 @@ namespace MediaBrowser.Server.Implementations.Intros
|
||||||
|
|
||||||
if (config.EnableIntrosFromMoviesInLibrary)
|
if (config.EnableIntrosFromMoviesInLibrary)
|
||||||
{
|
{
|
||||||
var inputItems = _libraryManager.GetItems(new InternalItemsQuery
|
var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name },
|
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||||
|
|
||||||
User = user
|
}, new string[]{});
|
||||||
|
|
||||||
}).Items;
|
|
||||||
|
|
||||||
var itemsWithTrailers = inputItems
|
var itemsWithTrailers = inputItems
|
||||||
.Where(i =>
|
.Where(i =>
|
||||||
|
@ -163,7 +161,7 @@ namespace MediaBrowser.Server.Implementations.Intros
|
||||||
private IEnumerable<IntroInfo> GetResult(BaseItem item, IEnumerable<ItemWithTrailer> candidates, CinemaModeConfiguration config, int? ratingLevel)
|
private IEnumerable<IntroInfo> GetResult(BaseItem item, IEnumerable<ItemWithTrailer> candidates, CinemaModeConfiguration config, int? ratingLevel)
|
||||||
{
|
{
|
||||||
var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?
|
var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?
|
||||||
GetCustomIntros(item) :
|
GetCustomIntros(config) :
|
||||||
new List<IntroInfo>();
|
new List<IntroInfo>();
|
||||||
|
|
||||||
var trailerLimit = config.TrailerLimit;
|
var trailerLimit = config.TrailerLimit;
|
||||||
|
@ -212,11 +210,11 @@ namespace MediaBrowser.Server.Implementations.Intros
|
||||||
return _serverConfig.GetConfiguration<CinemaModeConfiguration>("cinemamode");
|
return _serverConfig.GetConfiguration<CinemaModeConfiguration>("cinemamode");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IntroInfo> GetCustomIntros(BaseItem item)
|
private List<IntroInfo> GetCustomIntros(CinemaModeConfiguration options)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return GetCustomIntroFiles()
|
return GetCustomIntroFiles(options, true, false)
|
||||||
.OrderBy(i => Guid.NewGuid())
|
.OrderBy(i => Guid.NewGuid())
|
||||||
.Select(i => new IntroInfo
|
.Select(i => new IntroInfo
|
||||||
{
|
{
|
||||||
|
@ -230,17 +228,23 @@ namespace MediaBrowser.Server.Implementations.Intros
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<string> GetCustomIntroFiles(CinemaModeConfiguration options = null)
|
private IEnumerable<string> GetCustomIntroFiles(CinemaModeConfiguration options, bool enableCustomIntros, bool enableMediaInfoIntros)
|
||||||
{
|
{
|
||||||
options = options ?? GetOptions();
|
var list = new List<string>();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(options.CustomIntroPath))
|
if (enableCustomIntros && !string.IsNullOrWhiteSpace(options.CustomIntroPath))
|
||||||
{
|
{
|
||||||
return new List<string>();
|
list.AddRange(_fileSystem.GetFilePaths(options.CustomIntroPath, true)
|
||||||
|
.Where(_libraryManager.IsVideoFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
return _fileSystem.GetFilePaths(options.CustomIntroPath, true)
|
if (enableMediaInfoIntros && !string.IsNullOrWhiteSpace(options.MediaInfoIntroPath))
|
||||||
.Where(_libraryManager.IsVideoFile);
|
{
|
||||||
|
list.AddRange(_fileSystem.GetFilePaths(options.MediaInfoIntroPath, true)
|
||||||
|
.Where(_libraryManager.IsVideoFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.Distinct(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FilterByParentalRating(int? ratingLevel, BaseItem item)
|
private bool FilterByParentalRating(int? ratingLevel, BaseItem item)
|
||||||
|
@ -341,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Intros
|
||||||
|
|
||||||
public IEnumerable<string> GetAllIntroFiles()
|
public IEnumerable<string> GetAllIntroFiles()
|
||||||
{
|
{
|
||||||
return GetCustomIntroFiles();
|
return GetCustomIntroFiles(GetOptions(), true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsSupporter
|
private bool IsSupporter
|
||||||
|
|
|
@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shoulds the ignore.
|
/// Shoulds the ignore.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The args.</param>
|
/// <param name="fileInfo">The file information.</param>
|
||||||
|
/// <param name="parent">The parent.</param>
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||||
public bool ShouldIgnore(ItemResolveArgs args)
|
public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
|
||||||
{
|
{
|
||||||
var filename = args.FileInfo.Name;
|
var filename = fileInfo.Name;
|
||||||
|
var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
|
||||||
|
var path = fileInfo.FullName;
|
||||||
|
|
||||||
// Handle mac .DS_Store
|
// Handle mac .DS_Store
|
||||||
// https://github.com/MediaBrowser/MediaBrowser/issues/427
|
// https://github.com/MediaBrowser/MediaBrowser/issues/427
|
||||||
|
@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore hidden files and folders
|
// Ignore hidden files and folders
|
||||||
if (args.IsHidden)
|
if (isHidden)
|
||||||
{
|
{
|
||||||
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path));
|
if (parent == null)
|
||||||
|
{
|
||||||
|
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
|
||||||
|
|
||||||
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes these are marked hidden
|
// Sometimes these are marked hidden
|
||||||
if (_fileSystem.IsRootPath(args.Path))
|
if (_fileSystem.IsRootPath(path))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.IsDirectory)
|
if (fileInfo.IsDirectory)
|
||||||
{
|
{
|
||||||
// Ignore any folders in our list
|
// Ignore any folders in our list
|
||||||
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
|
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
|
||||||
|
@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore trailer folders but allow it at the collection level
|
if (parent != null)
|
||||||
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder))
|
|
||||||
{
|
{
|
||||||
return true;
|
// Ignore trailer folders but allow it at the collection level
|
||||||
}
|
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!(parent is AggregateFolder) && !(parent is UserRootFolder))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (args.Parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
// Don't resolve these into audio files
|
// Don't resolve these into audio files
|
||||||
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
|
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
|
||||||
|
|
|
@ -27,6 +27,7 @@ using MediaBrowser.Server.Implementations.Library.Validators;
|
||||||
using MediaBrowser.Server.Implementations.Logging;
|
using MediaBrowser.Server.Implementations.Logging;
|
||||||
using MediaBrowser.Server.Implementations.ScheduledTasks;
|
using MediaBrowser.Server.Implementations.ScheduledTasks;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -37,6 +38,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
|
using MediaBrowser.Model.Library;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MoreLinq;
|
using MoreLinq;
|
||||||
using SortOrder = MediaBrowser.Model.Entities.SortOrder;
|
using SortOrder = MediaBrowser.Model.Entities.SortOrder;
|
||||||
|
@ -142,6 +144,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
private readonly Func<ILibraryMonitor> _libraryMonitorFactory;
|
private readonly Func<ILibraryMonitor> _libraryMonitorFactory;
|
||||||
private readonly Func<IProviderManager> _providerManagerFactory;
|
private readonly Func<IProviderManager> _providerManagerFactory;
|
||||||
|
private readonly Func<IUserViewManager> _userviewManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _library items cache
|
/// The _library items cache
|
||||||
|
@ -169,7 +172,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="configurationManager">The configuration manager.</param>
|
/// <param name="configurationManager">The configuration manager.</param>
|
||||||
/// <param name="userDataRepository">The user data repository.</param>
|
/// <param name="userDataRepository">The user data repository.</param>
|
||||||
public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func<ILibraryMonitor> libraryMonitorFactory, IFileSystem fileSystem, Func<IProviderManager> providerManagerFactory)
|
public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func<ILibraryMonitor> libraryMonitorFactory, IFileSystem fileSystem, Func<IProviderManager> providerManagerFactory, Func<IUserViewManager> userviewManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_taskManager = taskManager;
|
_taskManager = taskManager;
|
||||||
|
@ -179,6 +182,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
_libraryMonitorFactory = libraryMonitorFactory;
|
_libraryMonitorFactory = libraryMonitorFactory;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_providerManagerFactory = providerManagerFactory;
|
_providerManagerFactory = providerManagerFactory;
|
||||||
|
_userviewManager = userviewManager;
|
||||||
ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>();
|
ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>();
|
||||||
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
|
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
|
@ -403,12 +407,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
foreach (var path in item.GetDeletePaths().ToList())
|
foreach (var path in item.GetDeletePaths().ToList())
|
||||||
{
|
{
|
||||||
if (_fileSystem.DirectoryExists(path))
|
if (_fileSystem.DirectoryExists(path))
|
||||||
{
|
{
|
||||||
_logger.Debug("Deleting path {0}", path);
|
_logger.Debug("Deleting path {0}", path);
|
||||||
_fileSystem.DeleteDirectory(path, true);
|
_fileSystem.DeleteDirectory(path, true);
|
||||||
}
|
}
|
||||||
else if (_fileSystem.FileExists(path))
|
else if (_fileSystem.FileExists(path))
|
||||||
{
|
{
|
||||||
_logger.Debug("Deleting path {0}", path);
|
_logger.Debug("Deleting path {0}", path);
|
||||||
_fileSystem.DeleteFile(path);
|
_fileSystem.DeleteFile(path);
|
||||||
|
@ -582,7 +586,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return null if ignore rules deem that we should do so
|
// Return null if ignore rules deem that we should do so
|
||||||
if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args)))
|
if (IgnoreFile(args.FileInfo, args.Parent))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -618,6 +622,11 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return ResolveItem(args);
|
return ResolveItem(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
|
||||||
|
{
|
||||||
|
return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
|
public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
|
||||||
{
|
{
|
||||||
var originalList = paths.ToList();
|
var originalList = paths.ToList();
|
||||||
|
@ -653,7 +662,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
|
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
|
||||||
{
|
{
|
||||||
var fileList = files.ToList();
|
var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
|
@ -704,7 +713,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
|
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(rootFolderPath);
|
_fileSystem.CreateDirectory(rootFolderPath);
|
||||||
|
|
||||||
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath));
|
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath));
|
||||||
|
|
||||||
|
@ -734,6 +743,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
folder = dbItem;
|
folder = dbItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (folder.ParentId != rootFolder.Id)
|
||||||
|
{
|
||||||
|
folder.ParentId = rootFolder.Id;
|
||||||
|
var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
|
||||||
rootFolder.AddVirtualChild(folder);
|
rootFolder.AddVirtualChild(folder);
|
||||||
|
|
||||||
RegisterItem(folder);
|
RegisterItem(folder);
|
||||||
|
@ -755,7 +771,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
|
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(userRootPath);
|
_fileSystem.CreateDirectory(userRootPath);
|
||||||
|
|
||||||
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
|
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
|
||||||
|
|
||||||
|
@ -1007,9 +1023,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable<IHasMetadata> items)
|
private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable<IHasMetadata> items)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validate and refresh the People sub-set of the IBN.
|
/// Validate and refresh the People sub-set of the IBN.
|
||||||
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
|
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
|
||||||
|
@ -1020,7 +1036,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
|
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
// Ensure the location is available.
|
// Ensure the location is available.
|
||||||
_fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
|
_fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
|
||||||
|
|
||||||
return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
|
return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
|
||||||
}
|
}
|
||||||
|
@ -1267,6 +1283,11 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User != null)
|
||||||
|
{
|
||||||
|
AddUserToQuery(query, query.User);
|
||||||
|
}
|
||||||
|
|
||||||
var result = ItemRepository.GetItemIdsList(query);
|
var result = ItemRepository.GetItemIdsList(query);
|
||||||
|
|
||||||
var items = result.Select(GetItemById).Where(i => i != null).ToArray();
|
var items = result.Select(GetItemById).Where(i => i != null).ToArray();
|
||||||
|
@ -1279,14 +1300,140 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public QueryResult<BaseItem> QueryItems(InternalItemsQuery query)
|
public QueryResult<BaseItem> QueryItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User != null)
|
||||||
|
{
|
||||||
|
AddUserToQuery(query, query.User);
|
||||||
|
}
|
||||||
|
|
||||||
return ItemRepository.GetItems(query);
|
return ItemRepository.GetItems(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Guid> GetItemIds(InternalItemsQuery query)
|
public List<Guid> GetItemIds(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User != null)
|
||||||
|
{
|
||||||
|
AddUserToQuery(query, query.User);
|
||||||
|
}
|
||||||
|
|
||||||
return ItemRepository.GetItemIdsList(query);
|
return ItemRepository.GetItemIdsList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds)
|
||||||
|
{
|
||||||
|
var parents = parentIds.Select(i => GetItemById(new Guid(i))).Where(i => i != null).ToList();
|
||||||
|
|
||||||
|
SetTopParentIdsOrAncestors(query, parents);
|
||||||
|
|
||||||
|
return GetItemIds(query).Select(GetItemById);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds)
|
||||||
|
{
|
||||||
|
var parents = parentIds.Select(i => GetItemById(new Guid(i))).Where(i => i != null).ToList();
|
||||||
|
|
||||||
|
SetTopParentIdsOrAncestors(query, parents);
|
||||||
|
|
||||||
|
return GetItems(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents)
|
||||||
|
{
|
||||||
|
if (parents.All(i =>
|
||||||
|
{
|
||||||
|
if ((i is ICollectionFolder) || (i is UserView))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
// Optimize by querying against top level views
|
||||||
|
query.TopParentIds = parents.SelectMany(i => GetTopParentsForQuery(i, query.User)).Select(i => i.Id.ToString("N")).ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We need to be able to query from any arbitrary ancestor up the tree
|
||||||
|
query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddUserToQuery(InternalItemsQuery query, User user)
|
||||||
|
{
|
||||||
|
if (query.AncestorIds.Length == 0 && !query.ParentId.HasValue && query.ChannelIds.Length == 0 && query.TopParentIds.Length == 0)
|
||||||
|
{
|
||||||
|
var userViews = _userviewManager().GetUserViews(new UserViewQuery
|
||||||
|
{
|
||||||
|
UserId = user.Id.ToString("N"),
|
||||||
|
IncludeHidden = true
|
||||||
|
|
||||||
|
}, CancellationToken.None).Result.ToList();
|
||||||
|
|
||||||
|
query.TopParentIds = userViews.SelectMany(i => GetTopParentsForQuery(i, user)).Select(i => i.Id.ToString("N")).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<BaseItem> GetTopParentsForQuery(BaseItem item, User user)
|
||||||
|
{
|
||||||
|
var view = item as UserView;
|
||||||
|
|
||||||
|
if (view != null)
|
||||||
|
{
|
||||||
|
if (string.Equals(view.ViewType, CollectionType.LiveTv))
|
||||||
|
{
|
||||||
|
return new[] { view };
|
||||||
|
}
|
||||||
|
if (string.Equals(view.ViewType, CollectionType.Channels))
|
||||||
|
{
|
||||||
|
// TODO: Return channels
|
||||||
|
return new[] { view };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate view into folders
|
||||||
|
if (view.DisplayParentId != Guid.Empty)
|
||||||
|
{
|
||||||
|
var displayParent = GetItemById(view.DisplayParentId);
|
||||||
|
if (displayParent != null)
|
||||||
|
{
|
||||||
|
return GetTopParentsForQuery(displayParent, user);
|
||||||
|
}
|
||||||
|
return new BaseItem[] { };
|
||||||
|
}
|
||||||
|
if (view.ParentId != Guid.Empty)
|
||||||
|
{
|
||||||
|
var displayParent = GetItemById(view.ParentId);
|
||||||
|
if (displayParent != null)
|
||||||
|
{
|
||||||
|
return GetTopParentsForQuery(displayParent, user);
|
||||||
|
}
|
||||||
|
return new BaseItem[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle grouping
|
||||||
|
if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType))
|
||||||
|
{
|
||||||
|
var collectionFolders = user.RootFolder.GetChildren(user, true).OfType<CollectionFolder>().Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase));
|
||||||
|
return collectionFolders.SelectMany(i => GetTopParentsForQuery(i, user));
|
||||||
|
}
|
||||||
|
return new BaseItem[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
var collectionFolder = item as CollectionFolder;
|
||||||
|
if (collectionFolder != null)
|
||||||
|
{
|
||||||
|
return collectionFolder.GetPhysicalParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
var topParent = item.GetTopParent();
|
||||||
|
if (topParent != null)
|
||||||
|
{
|
||||||
|
return new[] { topParent };
|
||||||
|
}
|
||||||
|
return new BaseItem[] { };
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the intros.
|
/// Gets the intros.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1579,9 +1726,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public IEnumerable<Folder> GetCollectionFolders(BaseItem item)
|
public IEnumerable<Folder> GetCollectionFolders(BaseItem item)
|
||||||
{
|
{
|
||||||
while (!(item.Parent is AggregateFolder) && item.Parent != null)
|
while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
|
||||||
{
|
{
|
||||||
item = item.Parent;
|
item = item.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
@ -1618,7 +1765,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.Parents
|
return item.GetParents()
|
||||||
.Select(GetConfiguredContentType)
|
.Select(GetConfiguredContentType)
|
||||||
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
|
||||||
}
|
}
|
||||||
|
@ -1655,16 +1802,16 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
private string GetTopFolderContentType(BaseItem item)
|
private string GetTopFolderContentType(BaseItem item)
|
||||||
{
|
{
|
||||||
while (!(item.Parent is AggregateFolder) && item.Parent != null)
|
|
||||||
{
|
|
||||||
item = item.Parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
|
||||||
|
{
|
||||||
|
item = item.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
return GetUserRootFolder().Children
|
return GetUserRootFolder().Children
|
||||||
.OfType<ICollectionFolder>()
|
.OfType<ICollectionFolder>()
|
||||||
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path))
|
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path))
|
||||||
|
@ -1681,7 +1828,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
string sortName,
|
string sortName,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
|
return GetNamedView(user, name, null, viewType, sortName, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserView> GetNamedView(string name,
|
public async Task<UserView> GetNamedView(string name,
|
||||||
|
@ -1699,10 +1846,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
var refresh = false;
|
var refresh = false;
|
||||||
|
|
||||||
if (item == null ||
|
if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
|
||||||
!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(path);
|
_fileSystem.CreateDirectory(path);
|
||||||
|
|
||||||
item = new UserView
|
item = new UserView
|
||||||
{
|
{
|
||||||
|
@ -1719,12 +1865,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
refresh = true;
|
refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
item.ViewType = viewType;
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!refresh)
|
if (!refresh)
|
||||||
{
|
{
|
||||||
refresh = (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
refresh = (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
||||||
|
@ -1750,40 +1890,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<UserView> GetNamedView(User user,
|
public async Task<UserView> GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string parentId,
|
string parentId,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
string uniqueId,
|
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(parentId))
|
var idValues = "38_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty) + (viewType ?? string.Empty);
|
||||||
{
|
|
||||||
throw new ArgumentNullException("parentId");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<UserView> GetNamedViewInternal(User user,
|
|
||||||
string name,
|
|
||||||
string parentId,
|
|
||||||
string viewType,
|
|
||||||
string sortName,
|
|
||||||
string uniqueId,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
var idValues = "37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty);
|
|
||||||
if (!string.IsNullOrWhiteSpace(uniqueId))
|
|
||||||
{
|
|
||||||
idValues += uniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = GetNewItemId(idValues, typeof(UserView));
|
var id = GetNewItemId(idValues, typeof(UserView));
|
||||||
|
|
||||||
|
@ -1795,7 +1909,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(path);
|
_fileSystem.CreateDirectory(path);
|
||||||
|
|
||||||
item = new UserView
|
item = new UserView
|
||||||
{
|
{
|
||||||
|
@ -1818,18 +1932,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.UserId.HasValue)
|
|
||||||
{
|
|
||||||
item.UserId = user.Id;
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
item.ViewType = viewType;
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
||||||
|
|
||||||
if (!refresh && item.DisplayParentId != Guid.Empty)
|
if (!refresh && item.DisplayParentId != Guid.Empty)
|
||||||
|
@ -1853,7 +1955,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
public async Task<UserView> GetShadowView(BaseItem parent,
|
public async Task<UserView> GetShadowView(BaseItem parent,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
string uniqueId,
|
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
|
@ -1864,11 +1965,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
var name = parent.Name;
|
var name = parent.Name;
|
||||||
var parentId = parent.Id;
|
var parentId = parent.Id;
|
||||||
|
|
||||||
var idValues = "37_namedview_" + name + parentId + (viewType ?? string.Empty);
|
var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty);
|
||||||
if (!string.IsNullOrWhiteSpace(uniqueId))
|
|
||||||
{
|
|
||||||
idValues += uniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = GetNewItemId(idValues, typeof(UserView));
|
var id = GetNewItemId(idValues, typeof(UserView));
|
||||||
|
|
||||||
|
@ -1899,12 +1996,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
item.ViewType = viewType;
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
|
||||||
|
|
||||||
if (!refresh && item.DisplayParentId != Guid.Empty)
|
if (!refresh && item.DisplayParentId != Guid.Empty)
|
||||||
|
@ -1924,7 +2015,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserView> GetNamedView(string name,
|
public async Task<UserView> GetNamedView(string name,
|
||||||
string parentId,
|
string parentId,
|
||||||
string viewType,
|
string viewType,
|
||||||
|
@ -1953,7 +2044,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(path);
|
_fileSystem.CreateDirectory(path);
|
||||||
|
|
||||||
item = new UserView
|
item = new UserView
|
||||||
{
|
{
|
||||||
|
@ -2200,21 +2291,21 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return ResolvePaths(files, directoryService, null, null)
|
return ResolvePaths(files, directoryService, null, null)
|
||||||
.OfType<Video>()
|
.OfType<Video>()
|
||||||
.Select(video =>
|
.Select(video =>
|
||||||
{
|
|
||||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
|
||||||
var dbItem = GetItemById(video.Id) as Video;
|
|
||||||
|
|
||||||
if (dbItem != null)
|
|
||||||
{
|
{
|
||||||
video = dbItem;
|
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||||
}
|
var dbItem = GetItemById(video.Id) as Video;
|
||||||
|
|
||||||
video.ExtraType = ExtraType.Trailer;
|
if (dbItem != null)
|
||||||
|
{
|
||||||
|
video = dbItem;
|
||||||
|
}
|
||||||
|
|
||||||
return video;
|
video.ExtraType = ExtraType.Trailer;
|
||||||
|
|
||||||
// Sort them so that the list can be easily compared for changes
|
return video;
|
||||||
}).OrderBy(i => i.Path).ToList();
|
|
||||||
|
// Sort them so that the list can be easily compared for changes
|
||||||
|
}).OrderBy(i => i.Path).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
||||||
|
@ -2386,7 +2477,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return ItemRepository.UpdatePeople(item.Id, people);
|
return ItemRepository.UpdatePeople(item.Id, people);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1,1);
|
private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1, 1);
|
||||||
public async Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex)
|
public async Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex)
|
||||||
{
|
{
|
||||||
foreach (var url in image.Path.Split('|'))
|
foreach (var url in image.Path.Split('|'))
|
||||||
|
@ -2425,4 +2516,4 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -80,15 +80,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var genreList = genres.ToList();
|
var genreList = genres.ToList();
|
||||||
|
|
||||||
var inputItems = _libraryManager.GetItems(new InternalItemsQuery
|
var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { typeof(Audio).Name },
|
||||||
|
|
||||||
Genres = genreList.ToArray(),
|
Genres = genreList.ToArray()
|
||||||
|
|
||||||
User = user
|
}, new string[] { });
|
||||||
|
|
||||||
}).Items;
|
|
||||||
|
|
||||||
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
item.Id = libraryManager.GetNewItemId(item.Path, item.GetType());
|
item.Id = libraryManager.GetNewItemId(item.Path, item.GetType());
|
||||||
|
|
||||||
item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
|
item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
item.Parents.Any(i => i.IsLocked);
|
item.GetParents().Any(i => i.IsLocked);
|
||||||
|
|
||||||
// Make sure DateCreated and DateModified have values
|
// Make sure DateCreated and DateModified have values
|
||||||
var fileInfo = directoryService.GetFile(item.Path);
|
var fileInfo = directoryService.GetFile(item.Path);
|
||||||
|
@ -78,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
EnsureName(item, args.FileInfo);
|
EnsureName(item, args.FileInfo);
|
||||||
|
|
||||||
item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
|
item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
item.Parents.Any(i => i.IsLocked);
|
item.GetParents().Any(i => i.IsLocked);
|
||||||
|
|
||||||
// Make sure DateCreated and DateModified have values
|
// Make sure DateCreated and DateModified have values
|
||||||
EnsureDates(fileSystem, item, args, true);
|
EnsureDates(fileSystem, item, args, true);
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
string collectionType,
|
string collectionType,
|
||||||
IDirectoryService directoryService)
|
IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
if (IsInvalid(parent, collectionType, files))
|
if (IsInvalid(parent, collectionType))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -77,16 +77,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
return ResolveVideos<MusicVideo>(parent, files, directoryService, false);
|
return ResolveVideos<MusicVideo>(parent, files, directoryService, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return ResolveVideos<Video>(parent, files, directoryService, false);
|
return ResolveVideos<Video>(parent, files, directoryService, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return ResolveVideos<Video>(parent, files, directoryService, collectionType, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(collectionType))
|
if (string.IsNullOrEmpty(collectionType))
|
||||||
{
|
{
|
||||||
// Owned items should just use the plain video type
|
// Owned items should just use the plain video type
|
||||||
|
@ -95,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
return ResolveVideos<Video>(parent, files, directoryService, false);
|
return ResolveVideos<Video>(parent, files, directoryService, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent is Series || parent.Parents.OfType<Series>().Any())
|
if (parent is Series || parent.GetParents().OfType<Series>().Any())
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +181,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
{
|
{
|
||||||
var collectionType = args.GetCollectionType();
|
var collectionType = args.GetCollectionType();
|
||||||
|
|
||||||
if (IsInvalid(args.Parent, collectionType, args.FileSystemChildren))
|
if (IsInvalid(args.Parent, collectionType))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -193,14 +189,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
// Find movies with their own folders
|
// Find movies with their own folders
|
||||||
if (args.IsDirectory)
|
if (args.IsDirectory)
|
||||||
{
|
{
|
||||||
|
var files = args.FileSystemChildren
|
||||||
|
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<MusicVideo>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(collectionType))
|
if (string.IsNullOrEmpty(collectionType))
|
||||||
|
@ -208,7 +208,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
// Owned items should just use the plain video type
|
// Owned items should just use the plain video type
|
||||||
if (args.Parent == null)
|
if (args.Parent == null)
|
||||||
{
|
{
|
||||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.HasParent<Series>())
|
if (args.HasParent<Series>())
|
||||||
|
@ -216,12 +216,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -246,11 +246,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
item = ResolveVideo<Movie>(args, true);
|
item = ResolveVideo<Movie>(args, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) ||
|
||||||
{
|
string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
||||||
item = ResolveVideo<Video>(args, false);
|
|
||||||
}
|
|
||||||
else if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
item = ResolveVideo<Video>(args, false);
|
item = ResolveVideo<Video>(args, false);
|
||||||
}
|
}
|
||||||
|
@ -494,7 +491,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInvalid(Folder parent, string collectionType, IEnumerable<FileSystemMetadata> files)
|
private bool IsInvalid(Folder parent, string collectionType)
|
||||||
{
|
{
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||||
// Not officially supported but in some cases we can handle it.
|
// Not officially supported but in some cases we can handle it.
|
||||||
if (season == null)
|
if (season == null)
|
||||||
{
|
{
|
||||||
season = parent.Parents.OfType<Season>().FirstOrDefault();
|
season = parent.GetParents().OfType<Season>().FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
|
// If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
|
||||||
|
|
|
@ -156,19 +156,18 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
|
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
|
||||||
|
|
||||||
var mediaItems = _libraryManager.GetItems(new InternalItemsQuery
|
var mediaItems = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
NameContains = searchTerm,
|
NameContains = searchTerm,
|
||||||
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
||||||
IncludeItemTypes = includeItemTypes.ToArray(),
|
IncludeItemTypes = includeItemTypes.ToArray(),
|
||||||
MaxParentalRating = user == null ? null : user.Policy.MaxParentalRating,
|
Limit = query.Limit,
|
||||||
Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 3) : null),
|
|
||||||
|
|
||||||
}).Items;
|
}, new string[] { });
|
||||||
|
|
||||||
// Add search hints based on item name
|
// Add search hints based on item name
|
||||||
hints.AddRange(mediaItems.Where(i => IncludeInSearch(i) && IsVisible(i, user)).Select(item =>
|
hints.AddRange(mediaItems.Where(IncludeInSearch).Select(item =>
|
||||||
{
|
{
|
||||||
var index = GetIndex(item.Name, searchTerm, terms);
|
var index = GetIndex(item.Name, searchTerm, terms);
|
||||||
|
|
||||||
|
@ -184,25 +183,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return Task.FromResult(returnValue);
|
return Task.FromResult(returnValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVisible(BaseItem item, User user)
|
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item is IItemByName)
|
|
||||||
{
|
|
||||||
var dual = item as IHasDualAccess;
|
|
||||||
if (dual == null || dual.IsAccessedByName)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.IsVisibleStandalone(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IncludeInSearch(BaseItem item)
|
private bool IncludeInSearch(BaseItem item)
|
||||||
{
|
{
|
||||||
var episode = item as Episode;
|
var episode = item as Episode;
|
||||||
|
|
|
@ -704,8 +704,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
Id = Guid.NewGuid(),
|
Id = Guid.NewGuid(),
|
||||||
DateCreated = DateTime.UtcNow,
|
DateCreated = DateTime.UtcNow,
|
||||||
DateModified = DateTime.UtcNow,
|
DateModified = DateTime.UtcNow,
|
||||||
UsesIdForConfigurationPath = true,
|
UsesIdForConfigurationPath = true
|
||||||
EnableUserViews = true
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Library
|
namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
|
@ -48,103 +49,63 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
if (!query.IncludeHidden)
|
||||||
|
{
|
||||||
|
folders = folders.Where(i =>
|
||||||
|
{
|
||||||
|
var hidden = i as IHiddenFromDisplay;
|
||||||
|
return hidden == null || !hidden.IsHiddenFromUser(user);
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
var plainFolderIds = user.Configuration.PlainFolderViews.Select(i => new Guid(i)).ToList();
|
var plainFolderIds = user.Configuration.PlainFolderViews.Select(i => new Guid(i)).ToList();
|
||||||
|
|
||||||
var standaloneFolders = folders
|
var groupedFolders = new List<ICollectionFolder>();
|
||||||
.Where(i => UserView.IsExcludedFromGrouping(i) || !user.IsFolderGrouped(i.Id))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var foldersWithViewTypes = folders
|
|
||||||
.Except(standaloneFolders)
|
|
||||||
.OfType<ICollectionFolder>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var list = new List<Folder>();
|
var list = new List<Folder>();
|
||||||
|
|
||||||
var enableUserViews = _config.Configuration.EnableUserViews || user.EnableUserViews;
|
foreach (var folder in folders)
|
||||||
|
|
||||||
if (enableUserViews)
|
|
||||||
{
|
{
|
||||||
foreach (var folder in standaloneFolders)
|
var collectionFolder = folder as ICollectionFolder;
|
||||||
{
|
var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
|
||||||
var collectionFolder = folder as ICollectionFolder;
|
|
||||||
var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
|
|
||||||
|
|
||||||
if (UserView.IsUserSpecific(folder))
|
if (UserView.IsUserSpecific(folder))
|
||||||
{
|
{
|
||||||
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
|
list.Add(await _libraryManager.GetNamedView(user, folder.Name, folder.Id.ToString("N"), folderViewType, null, cancellationToken).ConfigureAwait(false));
|
||||||
}
|
continue;
|
||||||
else if (plainFolderIds.Contains(folder.Id))
|
|
||||||
{
|
|
||||||
list.Add(await GetUserView(folder, folderViewType, false, string.Empty, cancellationToken).ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
else if (!string.IsNullOrWhiteSpace(folderViewType))
|
|
||||||
{
|
|
||||||
list.Add(await GetUserView(folder, folderViewType, true, string.Empty, cancellationToken).ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list.Add(folder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Deprecate this whole block
|
|
||||||
foreach (var folder in standaloneFolders)
|
|
||||||
{
|
|
||||||
var collectionFolder = folder as ICollectionFolder;
|
|
||||||
var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
|
|
||||||
|
|
||||||
if (UserView.IsUserSpecific(folder))
|
if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType))
|
||||||
{
|
{
|
||||||
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
|
list.Add(folder);
|
||||||
}
|
continue;
|
||||||
else if (plainFolderIds.Contains(folder.Id))
|
}
|
||||||
{
|
|
||||||
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, user, cancellationToken).ConfigureAwait(false));
|
if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
|
||||||
}
|
{
|
||||||
else if (!string.IsNullOrWhiteSpace(folderViewType))
|
groupedFolders.Add(collectionFolder);
|
||||||
{
|
continue;
|
||||||
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
|
}
|
||||||
}
|
|
||||||
else
|
if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
list.Add(folder);
|
list.Add(await GetUserView(folder, folderViewType, string.Empty, cancellationToken).ConfigureAwait(false));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add(folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user)))
|
foreach (var viewType in new[] { CollectionType.Movies, CollectionType.TvShows })
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (parents.Count > 0)
|
|
||||||
{
|
{
|
||||||
list.Add(await GetUserView(parents, list, CollectionType.TvShows, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false));
|
var parents = groupedFolders.Where(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType))
|
||||||
}
|
.ToList();
|
||||||
|
|
||||||
parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user)))
|
if (parents.Count > 0)
|
||||||
.ToList();
|
{
|
||||||
|
list.Add(await GetUserView(parents, viewType, string.Empty, user, query.PresetViews, cancellationToken).ConfigureAwait(false));
|
||||||
if (parents.Count > 0)
|
}
|
||||||
{
|
|
||||||
list.Add(await GetUserView(parents, list, CollectionType.Music, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user)))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (parents.Count > 0)
|
|
||||||
{
|
|
||||||
list.Add(await GetUserView(parents, list, CollectionType.Movies, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Games, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (parents.Count > 0)
|
|
||||||
{
|
|
||||||
list.Add(await GetUserView(parents, list, CollectionType.Games, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.Configuration.DisplayFoldersView)
|
if (user.Configuration.DisplayFoldersView)
|
||||||
|
@ -187,6 +148,18 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var index = orders.IndexOf(i.Id.ToString("N"));
|
var index = orders.IndexOf(i.Id.ToString("N"));
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
var view = i as UserView;
|
||||||
|
if (view != null)
|
||||||
|
{
|
||||||
|
if (view.DisplayParentId != Guid.Empty)
|
||||||
|
{
|
||||||
|
index = orders.IndexOf(view.DisplayParentId.ToString("N"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return index == -1 ? int.MaxValue : index;
|
return index == -1 ? int.MaxValue : index;
|
||||||
})
|
})
|
||||||
.ThenBy(sorted.IndexOf)
|
.ThenBy(sorted.IndexOf)
|
||||||
|
@ -207,32 +180,25 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return GetUserSubView(name, parentId, type, sortName, cancellationToken);
|
return GetUserSubView(name, parentId, type, sortName, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<UserView> GetUserView(List<ICollectionFolder> parents, List<Folder> currentViews, string viewType, string sortName, User user, bool enableUserViews, CancellationToken cancellationToken)
|
private async Task<Folder> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, string[] presetViews, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (parents.Count == 1 && parents.All(i => string.Equals((enableUserViews ? i.GetViewType(user) : i.CollectionType), viewType, StringComparison.OrdinalIgnoreCase)))
|
if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
var parentId = parents[0].Id;
|
if (!presetViews.Contains(viewType, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return (Folder)parents[0];
|
||||||
|
}
|
||||||
|
|
||||||
var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase);
|
return await GetUserView((Folder)parents[0], viewType, string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return await GetUserView((Folder)parents[0], viewType, enableRichView, string.Empty, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
|
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
|
||||||
return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
|
return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<UserView> GetUserView(Guid parentId, string name, string viewType, bool enableRichView, string sortName, User user, CancellationToken cancellationToken)
|
public Task<UserView> GetUserView(Folder parent, string viewType, string sortName, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
viewType = enableRichView ? viewType : null;
|
return _libraryManager.GetShadowView(parent, viewType, sortName, cancellationToken);
|
||||||
return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, null, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<UserView> GetUserView(Folder parent, string viewType, bool enableRichView, string sortName, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
viewType = enableRichView ? viewType : null;
|
|
||||||
|
|
||||||
return _libraryManager.GetShadowView(parent, viewType, sortName, null, cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
|
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
|
||||||
|
@ -243,16 +209,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
var currentUser = user;
|
var currentUser = user;
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i =>
|
var libraryItems = GetItemsForLatestItems(user, request.ParentId, includeTypes, request.Limit ?? 10).Where(i =>
|
||||||
{
|
{
|
||||||
if (includeTypes.Length > 0)
|
|
||||||
{
|
|
||||||
if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.IsPlayed.HasValue)
|
if (request.IsPlayed.HasValue)
|
||||||
{
|
{
|
||||||
var val = request.IsPlayed.Value;
|
var val = request.IsPlayed.Value;
|
||||||
|
@ -262,29 +220,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return i.LocationType != LocationType.Virtual && !i.IsFolder;
|
return true;
|
||||||
};
|
});
|
||||||
|
|
||||||
// Avoid implicitly captured closure
|
|
||||||
var libraryItems = string.IsNullOrEmpty(request.ParentId) && user != null ?
|
|
||||||
GetItemsConfiguredForLatest(user, filter) :
|
|
||||||
GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, filter);
|
|
||||||
|
|
||||||
libraryItems = libraryItems.OrderByDescending(i => i.DateCreated);
|
|
||||||
|
|
||||||
if (request.IsPlayed.HasValue)
|
|
||||||
{
|
|
||||||
var takeLimit = (request.Limit ?? 20) * 20;
|
|
||||||
libraryItems = libraryItems.Take(takeLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid implicitly captured closure
|
|
||||||
var items = libraryItems
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var list = new List<Tuple<BaseItem, List<BaseItem>>>();
|
var list = new List<Tuple<BaseItem, List<BaseItem>>>();
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in libraryItems)
|
||||||
{
|
{
|
||||||
// Only grab the index container for media
|
// Only grab the index container for media
|
||||||
var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
|
var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
|
||||||
|
@ -316,59 +257,34 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter)
|
private IEnumerable<BaseItem> GetItemsForLatestItems(User user, string parentId, string[] includeItemTypes, int limit)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(parentId))
|
var parentIds = string.IsNullOrEmpty(parentId)
|
||||||
|
? new string[] { }
|
||||||
|
: new[] { parentId };
|
||||||
|
|
||||||
|
if (parentIds.Length == 0)
|
||||||
{
|
{
|
||||||
var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
|
parentIds = user.RootFolder.GetChildren(user, true)
|
||||||
|
.OfType<Folder>()
|
||||||
if (!string.IsNullOrWhiteSpace(userId))
|
.Select(i => i.Id.ToString("N"))
|
||||||
{
|
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i))
|
||||||
var user = userManager.GetUserById(userId);
|
.ToArray();
|
||||||
|
|
||||||
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 user
|
|
||||||
.RootFolder
|
|
||||||
.GetRecursiveChildren(user, filter)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return libraryManager
|
var excludeItemTypes = includeItemTypes.Length == 0 ? new[] { "ChannelItem", "LiveTvItem", typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name } : new string[] { };
|
||||||
.RootFolder
|
|
||||||
.GetRecursiveChildren(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<BaseItem> GetItemsConfiguredForLatest(User user, Func<BaseItem, bool> filter)
|
return _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
// Avoid implicitly captured closure
|
IncludeItemTypes = includeItemTypes,
|
||||||
var currentUser = user;
|
SortOrder = SortOrder.Descending,
|
||||||
|
SortBy = new[] { ItemSortBy.DateCreated },
|
||||||
|
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
|
||||||
|
ExcludeItemTypes = excludeItemTypes,
|
||||||
|
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
||||||
|
Limit = limit * 20
|
||||||
|
|
||||||
return user.RootFolder.GetChildren(user, true)
|
}, parentIds);
|
||||||
.OfType<Folder>()
|
|
||||||
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N")))
|
|
||||||
.SelectMany(i => i.GetRecursiveChildren(currentUser, filter))
|
|
||||||
.DistinctBy(i => i.Id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,6 +560,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
item.ExternalId = channelInfo.Id;
|
item.ExternalId = channelInfo.Id;
|
||||||
|
|
||||||
|
if (!item.ParentId.Equals(parentFolderId))
|
||||||
|
{
|
||||||
|
isNew = true;
|
||||||
|
}
|
||||||
|
item.ParentId = parentFolderId;
|
||||||
|
|
||||||
item.ChannelType = channelInfo.ChannelType;
|
item.ChannelType = channelInfo.ChannelType;
|
||||||
item.ServiceName = serviceName;
|
item.ServiceName = serviceName;
|
||||||
item.Number = channelInfo.Number;
|
item.Number = channelInfo.Number;
|
||||||
|
@ -622,6 +628,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!item.ParentId.Equals(channel.Id))
|
||||||
|
{
|
||||||
|
forceUpdate = true;
|
||||||
|
}
|
||||||
|
item.ParentId = channel.Id;
|
||||||
|
|
||||||
//item.ChannelType = channelType;
|
//item.ChannelType = channelType;
|
||||||
if (!string.Equals(item.ServiceName, serviceName, StringComparison.Ordinal))
|
if (!string.Equals(item.ServiceName, serviceName, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
|
@ -774,6 +786,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
recording.IsSeries = info.IsSeries;
|
recording.IsSeries = info.IsSeries;
|
||||||
|
|
||||||
|
if (!item.ParentId.Equals(parentFolderId))
|
||||||
|
{
|
||||||
|
dataChanged = true;
|
||||||
|
}
|
||||||
|
item.ParentId = parentFolderId;
|
||||||
|
|
||||||
if (!item.HasImage(ImageType.Primary))
|
if (!item.HasImage(ImageType.Primary))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(info.ImagePath))
|
if (!string.IsNullOrWhiteSpace(info.ImagePath))
|
||||||
|
@ -851,7 +869,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
{
|
{
|
||||||
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
var internalQuery = new InternalItemsQuery
|
var internalQuery = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||||
MinEndDate = query.MinEndDate,
|
MinEndDate = query.MinEndDate,
|
||||||
|
@ -869,16 +887,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
SortOrder = query.SortOrder ?? SortOrder.Ascending
|
SortOrder = query.SortOrder ?? SortOrder.Ascending
|
||||||
};
|
};
|
||||||
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
internalQuery.MaxParentalRating = user.Policy.MaxParentalRating;
|
|
||||||
|
|
||||||
if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram))
|
|
||||||
{
|
|
||||||
internalQuery.HasParentalRating = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasAired.HasValue)
|
if (query.HasAired.HasValue)
|
||||||
{
|
{
|
||||||
if (query.HasAired.Value)
|
if (query.HasAired.Value)
|
||||||
|
@ -913,7 +921,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(query.UserId);
|
var user = _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
var internalQuery = new InternalItemsQuery
|
var internalQuery = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||||
IsAiring = query.IsAiring,
|
IsAiring = query.IsAiring,
|
||||||
|
@ -922,16 +930,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
IsKids = query.IsKids
|
IsKids = query.IsKids
|
||||||
};
|
};
|
||||||
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
internalQuery.MaxParentalRating = user.Policy.MaxParentalRating;
|
|
||||||
|
|
||||||
if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram))
|
|
||||||
{
|
|
||||||
internalQuery.HasParentalRating = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasAired.HasValue)
|
if (query.HasAired.HasValue)
|
||||||
{
|
{
|
||||||
if (query.HasAired.Value)
|
if (query.HasAired.Value)
|
||||||
|
@ -1399,7 +1397,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
|
|
||||||
await RefreshRecordings(cancellationToken).ConfigureAwait(false);
|
await RefreshRecordings(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var internalQuery = new InternalItemsQuery
|
var internalQuery = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }
|
IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }
|
||||||
};
|
};
|
||||||
|
@ -1409,8 +1407,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
internalQuery.ChannelIds = new[] { query.ChannelId };
|
internalQuery.ChannelIds = new[] { query.ChannelId };
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryResult = _libraryManager.GetItems(internalQuery);
|
var queryResult = _libraryManager.GetItems(internalQuery, new string[] { });
|
||||||
IEnumerable<ILiveTvRecording> recordings = queryResult.Items.Cast<ILiveTvRecording>();
|
IEnumerable<ILiveTvRecording> recordings = queryResult.Cast<ILiveTvRecording>();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(query.Id))
|
if (!string.IsNullOrEmpty(query.Id))
|
||||||
{
|
{
|
||||||
|
@ -1516,6 +1514,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
{
|
{
|
||||||
dto.ChannelName = channel.Name;
|
dto.ChannelName = channel.Name;
|
||||||
|
dto.MediaType = channel.MediaType;
|
||||||
|
|
||||||
if (channel.HasImage(ImageType.Primary))
|
if (channel.HasImage(ImageType.Primary))
|
||||||
{
|
{
|
||||||
|
@ -1812,7 +1811,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
var programs = _libraryManager.GetItems(new InternalItemsQuery
|
var programs = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||||
ChannelIds = new[] { id },
|
ChannelIds = new[] { id },
|
||||||
|
@ -1821,7 +1820,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
SortBy = new[] { "StartDate" }
|
SortBy = new[] { "StartDate" }
|
||||||
|
|
||||||
}).Items.Cast<LiveTvProgram>();
|
}, new string[] { }).Cast<LiveTvProgram>();
|
||||||
|
|
||||||
var currentProgram = programs.FirstOrDefault();
|
var currentProgram = programs.FirstOrDefault();
|
||||||
|
|
||||||
|
@ -1836,7 +1835,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
var programs = _libraryManager.GetItems(new InternalItemsQuery
|
var programs = _libraryManager.GetItems(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||||
ChannelIds = new[] { channel.Id.ToString("N") },
|
ChannelIds = new[] { channel.Id.ToString("N") },
|
||||||
|
@ -1845,7 +1844,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
SortBy = new[] { "StartDate" }
|
SortBy = new[] { "StartDate" }
|
||||||
|
|
||||||
}).Items.Cast<LiveTvProgram>();
|
}, new string[] { }).Cast<LiveTvProgram>();
|
||||||
|
|
||||||
var currentProgram = programs.FirstOrDefault();
|
var currentProgram = programs.FirstOrDefault();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||||
|
{
|
||||||
|
public class SatIpDiscovery : IServerEntryPoint
|
||||||
|
{
|
||||||
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
|
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
|
public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient)
|
||||||
|
{
|
||||||
|
_deviceDiscovery = deviceDiscovery;
|
||||||
|
_config = config;
|
||||||
|
_logger = logger;
|
||||||
|
_liveTvManager = liveTvManager;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
_deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
|
||||||
|
{
|
||||||
|
//string server = null;
|
||||||
|
//if (e.Headers.TryGetValue("SERVER", out server) && server.IndexOf("HDHomeRun", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
//{
|
||||||
|
// string location;
|
||||||
|
// if (e.Headers.TryGetValue("Location", out location))
|
||||||
|
// {
|
||||||
|
// //_logger.Debug("HdHomerun found at {0}", location);
|
||||||
|
|
||||||
|
// // Just get the beginning of the url
|
||||||
|
// Uri uri;
|
||||||
|
// if (Uri.TryCreate(location, UriKind.Absolute, out uri))
|
||||||
|
// {
|
||||||
|
// var apiUrl = location.Replace(uri.LocalPath, String.Empty, StringComparison.OrdinalIgnoreCase)
|
||||||
|
// .TrimEnd('/');
|
||||||
|
|
||||||
|
// //_logger.Debug("HdHomerun api url: {0}", apiUrl);
|
||||||
|
// AddDevice(apiUrl);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void AddDevice(string url)
|
||||||
|
{
|
||||||
|
await _semaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var options = GetConfiguration();
|
||||||
|
|
||||||
|
if (options.TunerHosts.Any(i =>
|
||||||
|
string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
UriEquals(i.Url, url)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip off the port
|
||||||
|
url = new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped).TrimEnd('/');
|
||||||
|
|
||||||
|
await TestUrl(url).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await _liveTvManager.SaveTunerHost(new TunerHostInfo
|
||||||
|
{
|
||||||
|
Type = SatIpHost.DeviceType,
|
||||||
|
Url = url
|
||||||
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error saving device", ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TestUrl(string url)
|
||||||
|
{
|
||||||
|
// Test it by pulling down the lineup
|
||||||
|
using (await _httpClient.Get(new HttpRequestOptions
|
||||||
|
{
|
||||||
|
Url = string.Format("{0}/lineup.json", url),
|
||||||
|
CancellationToken = CancellationToken.None
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UriEquals(string savedUri, string location)
|
||||||
|
{
|
||||||
|
return string.Equals(NormalizeUrl(location), NormalizeUrl(savedUri), StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NormalizeUrl(string url)
|
||||||
|
{
|
||||||
|
if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
url = "http://" + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = url.TrimEnd('/');
|
||||||
|
|
||||||
|
// Strip off the port
|
||||||
|
return new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiveTvOptions GetConfiguration()
|
||||||
|
{
|
||||||
|
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||||
|
{
|
||||||
|
public class SatIpHost /*: BaseTunerHost*/
|
||||||
|
{
|
||||||
|
//public SatIpHost(IConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder)
|
||||||
|
// : base(config, logger, jsonSerializer, mediaEncoder)
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken)
|
||||||
|
//{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static string DeviceType
|
||||||
|
{
|
||||||
|
get { return "satip"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//public override string Type
|
||||||
|
//{
|
||||||
|
// get { return DeviceType; }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
|
//{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override Task<MediaSourceInfo> GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken)
|
||||||
|
//{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
|
//{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override bool IsValidChannelId(string channelId)
|
||||||
|
//{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
"AppDeviceValues": "App: {0}, Device: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
||||||
"FolderTypeMixed": "Mixed content",
|
"FolderTypeMixed": "Mixed content",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
"AppDeviceValues": "App: {0}, Device: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
||||||
"FolderTypeMixed": "\u0421\u043c\u0435\u0441\u0435\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435",
|
"FolderTypeMixed": "\u0421\u043c\u0435\u0441\u0435\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435",
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Dispositiu: {1}",
|
"AppDeviceValues": "App: {0}, Dispositiu: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}",
|
"UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}",
|
||||||
"FolderTypeMixed": "Mixed content",
|
"FolderTypeMixed": "Contingut barrejat",
|
||||||
"FolderTypeMovies": "Pel\u00b7l\u00edcules",
|
"FolderTypeMovies": "Pel\u00b7l\u00edcules",
|
||||||
"FolderTypeMusic": "M\u00fasica",
|
"FolderTypeMusic": "M\u00fasica",
|
||||||
"FolderTypeAdultVideos": "Adult videos",
|
"FolderTypeAdultVideos": "V\u00eddeos per adults",
|
||||||
"FolderTypePhotos": "Fotos",
|
"FolderTypePhotos": "Fotos",
|
||||||
"FolderTypeMusicVideos": "V\u00eddeos musicals",
|
"FolderTypeMusicVideos": "V\u00eddeos musicals",
|
||||||
"FolderTypeHomeVideos": "V\u00eddeos dom\u00e8stics",
|
"FolderTypeHomeVideos": "V\u00eddeos dom\u00e8stics",
|
||||||
|
@ -115,7 +116,7 @@
|
||||||
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
||||||
"AuthenticationSucceededWithUserName": "{0} autenticat correctament",
|
"AuthenticationSucceededWithUserName": "{0} autenticat correctament",
|
||||||
"DeviceOfflineWithName": "{0} has disconnected",
|
"DeviceOfflineWithName": "{0} has disconnected",
|
||||||
"UserLockedOutWithName": "User {0} has been locked out",
|
"UserLockedOutWithName": "L'usuari {0} ha estat blocat",
|
||||||
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
||||||
"UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}",
|
"UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
|
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
|
||||||
|
@ -157,13 +158,13 @@
|
||||||
"HeaderVideo": "V\u00eddeo",
|
"HeaderVideo": "V\u00eddeo",
|
||||||
"HeaderEmbeddedImage": "Embedded image",
|
"HeaderEmbeddedImage": "Embedded image",
|
||||||
"HeaderResolution": "Resolution",
|
"HeaderResolution": "Resolution",
|
||||||
"HeaderSubtitles": "Subtitles",
|
"HeaderSubtitles": "Subt\u00edtols",
|
||||||
"HeaderGenres": "Genres",
|
"HeaderGenres": "Genres",
|
||||||
"HeaderCountries": "Countries",
|
"HeaderCountries": "Countries",
|
||||||
"HeaderStatus": "Estat",
|
"HeaderStatus": "Estat",
|
||||||
"HeaderTracks": "Tracks",
|
"HeaderTracks": "Tracks",
|
||||||
"HeaderMusicArtist": "M\u00fasic",
|
"HeaderMusicArtist": "M\u00fasic",
|
||||||
"HeaderLocked": "Locked",
|
"HeaderLocked": "Blocat",
|
||||||
"HeaderStudios": "Estudis",
|
"HeaderStudios": "Estudis",
|
||||||
"HeaderActor": "Actors",
|
"HeaderActor": "Actors",
|
||||||
"HeaderComposer": "Compositors",
|
"HeaderComposer": "Compositors",
|
||||||
|
|
|
@ -174,5 +174,6 @@
|
||||||
"HeaderWriter": "Writers",
|
"HeaderWriter": "Writers",
|
||||||
"HeaderParentalRatings": "Parental Ratings",
|
"HeaderParentalRatings": "Parental Ratings",
|
||||||
"HeaderCommunityRatings": "Community ratings",
|
"HeaderCommunityRatings": "Community ratings",
|
||||||
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
|
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.",
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete."
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "Aplikace: {0}, Za\u0159\u00edzen\u00ed: {1}",
|
"AppDeviceValues": "Aplikace: {0}, Za\u0159\u00edzen\u00ed: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} pr\u00e1v\u011b stahuje {1}",
|
"UserDownloadingItemWithValues": "{0} pr\u00e1v\u011b stahuje {1}",
|
||||||
"FolderTypeMixed": "Sm\u00ed\u0161en\u00fd obsah",
|
"FolderTypeMixed": "Sm\u00ed\u0161en\u00fd obsah",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Enhed: {1}",
|
"AppDeviceValues": "App: {0}, Enhed: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} henter {1}",
|
"UserDownloadingItemWithValues": "{0} henter {1}",
|
||||||
"FolderTypeMixed": "Blandet indhold",
|
"FolderTypeMixed": "Blandet indhold",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Ger\u00e4t: {1}",
|
"AppDeviceValues": "App: {0}, Ger\u00e4t: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} l\u00e4dt {1} herunter",
|
"UserDownloadingItemWithValues": "{0} l\u00e4dt {1} herunter",
|
||||||
"FolderTypeMixed": "Gemischte Inhalte",
|
"FolderTypeMixed": "Gemischte Inhalte",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
"AppDeviceValues": "App: {0}, Device: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
||||||
"FolderTypeMixed": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf",
|
"FolderTypeMixed": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf",
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user