Merge branch 'dev' into beta

This commit is contained in:
Luke Pulverenti 2016-01-12 15:03:56 -05:00
commit 21f1d96ee9
117 changed files with 2168 additions and 1821 deletions

View file

@ -198,50 +198,6 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
}
protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem,bool> filter)
{
if (!string.IsNullOrEmpty(parentId))
{
var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return folder
.GetRecursiveChildren(user, filter)
.ToList();
}
return folder
.GetRecursiveChildren(filter);
}
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return userManager
.GetUserById(userId)
.RootFolder
.GetRecursiveChildren(user, filter)
.ToList();
}
return libraryManager
.RootFolder
.GetRecursiveChildren(filter);
}
/// <summary>
/// Deslugs an artist name by finding the correct entry in the library
/// </summary>

View file

@ -102,12 +102,16 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public object Get(GetGameSystemSummaries request)
{
var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is GameSystem)
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(GameSystem).Name }
};
var parentIds = new string[] { } ;
var gameSystems = _libraryManager.GetItems(query, parentIds)
.Cast<GameSystem>()
.ToList();
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
var result = gameSystems
.Select(i => GetSummary(i, user))
.ToList();
@ -119,8 +123,15 @@ namespace MediaBrowser.Api
public object Get(GetPlayerIndex request)
{
var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game)
.Cast<Game>();
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Game).Name }
};
var parentIds = new string[] { };
var games = _libraryManager.GetItems(query, parentIds)
.Cast<Game>()
.ToList();
var lookup = games
.ToLookup(i => i.PlayersSupported ?? -1)

View file

@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
public object Get(GetMediaFolders request)
{
var items = _libraryManager.GetUserRootFolder().Children.OrderBy(i => i.SortName).ToList();
var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
if (request.IsHidden.HasValue)
{
@ -610,7 +610,7 @@ namespace MediaBrowser.Api.Library
var dtoOptions = GetDtoOptions(request);
BaseItem parent = item.Parent;
BaseItem parent = item.GetParent();
while (parent != null)
{
@ -621,7 +621,7 @@ namespace MediaBrowser.Api.Library
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
parent = parent.Parent;
parent = parent.GetParent();
}
return baseItemDtos.ToList();
@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
private BaseItem TranslateParentItem(BaseItem item, User user)
{
if (item.Parent is AggregateFolder)
if (item.GetParent() is AggregateFolder)
{
return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
}
@ -677,6 +677,50 @@ namespace MediaBrowser.Api.Library
return ToOptimizedSerializedResultUsingCache(counts);
}
private IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter)
{
if (!string.IsNullOrEmpty(parentId))
{
var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return folder
.GetRecursiveChildren(user, filter)
.ToList();
}
return folder
.GetRecursiveChildren(filter);
}
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return userManager
.GetUserById(userId)
.RootFolder
.GetRecursiveChildren(user, filter)
.ToList();
}
return libraryManager
.RootFolder
.GetRecursiveChildren(filter);
}
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{
if (!string.IsNullOrWhiteSpace(userId))
@ -817,9 +861,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
item = item.Parent;
item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
@ -860,9 +904,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
item = item.Parent;
item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);

View file

@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarMovies request)
{
var result = await GetSimilarItemsResult(
// Strip out secondary versions
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@ -128,10 +125,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarTrailers request)
{
var result = await GetSimilarItemsResult(
// Strip out secondary versions
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@ -140,8 +134,12 @@ namespace MediaBrowser.Api.Movies
{
var user = _userManager.GetUserById(request.UserId);
IEnumerable<BaseItem> movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Movie);
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name }
};
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
var movies = _libraryManager.GetItems(query, parentIds);
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
var listEligibleForCategories = new List<BaseItem>();
@ -184,21 +182,27 @@ namespace MediaBrowser.Api.Movies
return ToOptimizedResult(result);
}
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
{
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var item = string.IsNullOrEmpty(request.Id) ?
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
var inputItems = user == null
? _libraryManager.RootFolder.GetRecursiveChildren(filter)
: user.RootFolder.GetRecursiveChildren(user, filter);
var list = inputItems.ToList();
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name }
};
var parentIds = new string[] { };
var list = _libraryManager.GetItems(query, parentIds)
.Where(i =>
{
// Strip out secondary versions
var v = i as Video;
return v != null && !v.PrimaryVersionId.HasValue;
})
.ToList();
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
{
@ -379,9 +383,10 @@ namespace MediaBrowser.Api.Movies
{
foreach (var name in names)
{
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
{
Person = name
});
var items = allMovies

View file

@ -283,7 +283,7 @@ namespace MediaBrowser.Api
private T GetParentWithImage<T>(BaseItem item, ImageType type)
where T : BaseItem
{
return item.Parents.OfType<T>().FirstOrDefault(i => i.HasImage(type));
return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
}
}
}

View file

@ -68,11 +68,7 @@ namespace MediaBrowser.Api
_config.Configuration.EnableLocalizedGuids = true;
_config.Configuration.MergeMetadataAndImagesByName = true;
_config.Configuration.EnableStandaloneMetadata = true;
_config.Configuration.EnableLibraryMetadataSubFolder = true;
_config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.DisableXmlSavers = true;
_config.Configuration.DisableStartupScan = true;
_config.Configuration.EnableUserViews = true;
_config.Configuration.EnableDateLastRefresh = true;
_config.SaveConfiguration();
}

View file

@ -159,7 +159,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string StartItemId { get; set; }
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
@ -273,29 +273,28 @@ namespace MediaBrowser.Api
{
var user = _userManager.GetUserById(request.UserId);
var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode);
var itemsList = _libraryManager
.Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending)
.Cast<Episode>()
.ToList();
var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList();
var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime();
var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList();
previousEpisodes.AddRange(unairedEpisodes);
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit);
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
SortOrder = SortOrder.Ascending,
MinPremiereDate = minPremiereDate,
StartIndex = request.StartIndex,
Limit = request.Limit
}, parentIds);
var options = GetDtoOptions(request);
var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray();
var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
var result = new ItemsResult
{
TotalRecordCount = itemsList.Count,
TotalRecordCount = itemsResult.TotalRecordCount,
Items = returnItems
};
@ -440,7 +439,7 @@ namespace MediaBrowser.Api
}
episodes = season.GetEpisodes(user);
}
}
else if (request.Season.HasValue)
{
var series = _libraryManager.GetItemById(request.Id) as Series;
@ -495,7 +494,7 @@ namespace MediaBrowser.Api
.ToList();
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
var dtoOptions = GetDtoOptions(request);
var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user)

View file

@ -206,6 +206,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; }
public string GenreIds { get; set; }
[ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string OfficialRatings { get; set; }
@ -385,6 +387,11 @@ namespace MediaBrowser.Api.UserLibrary
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetGenreIds()
{
return (GenreIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetPersonTypes()
{
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

View file

@ -112,6 +112,11 @@ namespace MediaBrowser.Api.UserLibrary
user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem;
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
{
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
}
// Default list type = children
if (!string.IsNullOrEmpty(request.Ids))
@ -211,6 +216,7 @@ namespace MediaBrowser.Api.UserLibrary
Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(),
GenreIds = request.GetGenreIds(),
Studios = request.GetStudios(),
StudioIds = request.GetStudioIds(),
Person = request.Person,
@ -423,15 +429,6 @@ namespace MediaBrowser.Api.UserLibrary
return false;
}
// Min index number
if (request.MinIndexNumber.HasValue)
{
if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
{
return false;
}
}
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{

View file

@ -26,6 +26,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
public bool? IncludeExternalContent { get; set; }
public string PresetViews { get; set; }
}
[Route("/Users/{UserId}/SpecialViewOptions", "GET")]
@ -75,9 +77,24 @@ namespace MediaBrowser.Api.UserLibrary
query.IncludeExternalContent = request.IncludeExternalContent.Value;
}
if (!string.IsNullOrWhiteSpace(request.PresetViews))
{
query.PresetViews = request.PresetViews.Split(',');
}
var app = AuthorizationContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
{
query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
}
//query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
var dtoOptions = GetDtoOptions(request);
dtoOptions.Fields = new List<ItemFields>();
dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);
var user = _userManager.GetUserById(request.UserId);
@ -123,7 +140,7 @@ namespace MediaBrowser.Api.UserLibrary
var views = user.RootFolder
.GetChildren(user, true)
.OfType<Folder>()
.Where(i => !UserView.IsExcludedFromGrouping(i))
.Where(UserView.IsEligibleForGrouping)
.ToList();
var list = views
@ -141,9 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
private bool IsEligibleForSpecialView(ICollectionFolder view)
{
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
return UserView.IsEligibleForEnhancedView(view.CollectionType);
}
}

View file

@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
return UnratedItem.ChannelContent;
}
protected override string CreateUserDataKey()

View file

@ -6,6 +6,7 @@ using System;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels
@ -20,6 +21,11 @@ namespace MediaBrowser.Controller.Channels
return false;
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.ChannelContent;
}
[IgnoreDataMember]
public override bool SupportsLocalMetadata
{

View file

@ -42,9 +42,9 @@ namespace MediaBrowser.Controller.Channels
return ExternalId;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
return UnratedItem.ChannelContent;
}
[IgnoreDataMember]

View file

@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
public List<string> Tags { get; set; }
public ExtraType? ExtraType { get; set; }
/// <summary>
/// Gets or sets the artist.
/// </summary>
/// <value>The artist.</value>
public List<string> Artists { get; set; }
public List<string> AlbumArtists { get; set; }
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
[IgnoreDataMember]
public bool IsThemeMedia
{
@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
{
Artists = new List<string>();
AlbumArtists = new List<string>();
Tags = new List<string>();
}
[IgnoreDataMember]
@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
locationType != LocationType.Virtual;
}
/// <summary>
/// Gets or sets the artist.
/// </summary>
/// <value>The artist.</value>
public List<string> Artists { get; set; }
public List<string> AlbumArtists { get; set; }
[IgnoreDataMember]
public List<string> AllArtists
{
@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
[IgnoreDataMember]
public MusicAlbum AlbumEntity
{
@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.CreateUserDataKey();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
return UnratedItem.Music;
}
public SongInfo GetLookupInfo()

View file

@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
return Parents.OfType<MusicArtist>().FirstOrDefault();
return GetParents().OfType<MusicArtist>().FirstOrDefault();
}
}
@ -110,13 +110,18 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
}
public AlbumInfo GetLookupInfo()
{
var id = GetItemLookupInfo<AlbumInfo>();
id.AlbumArtists = AlbumArtists;
var artist = Parents.OfType<MusicArtist>().FirstOrDefault();
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
if (artist != null)
{

View file

@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
}
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
var items = GetRecursiveChildren().ToList();

View file

@ -17,19 +17,8 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
public string SeriesName { get; set; }
public Book()
{
Tags = new List<string>();
}
public override bool CanDownload()
{
var locationType = LocationType;
@ -37,9 +26,9 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Book);
return UnratedItem.Book;
}
public BookInfo GetLookupInfo()
@ -48,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(SeriesName))
{
info.SeriesName = Parents.Select(i => i.Name).FirstOrDefault();
info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault();
}
else
{

View file

@ -181,9 +181,7 @@ namespace MediaBrowser.Controller.Entities
}
private List<LinkedChild> GetLinkedChildrenInternal()
{
return LibraryManager.RootFolder.Children
.OfType<Folder>()
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
return GetPhysicalParents()
.SelectMany(c => c.LinkedChildren)
.ToList();
}
@ -199,11 +197,14 @@ namespace MediaBrowser.Controller.Entities
private IEnumerable<BaseItem> GetActualChildren()
{
return
LibraryManager.RootFolder.Children
return GetPhysicalParents().SelectMany(c => c.Children);
}
public IEnumerable<Folder> GetPhysicalParents()
{
return LibraryManager.RootFolder.Children
.OfType<Folder>()
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
.SelectMany(c => c.Children);
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
}
[IgnoreDataMember]

View file

@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
public List<string> Tags { get; set; }
public Folder()
{
@ -36,7 +35,6 @@ namespace MediaBrowser.Controller.Entities
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
Tags = new List<string>();
}
[IgnoreDataMember]
@ -151,7 +149,15 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
}
private static bool EnableNewFolderQuerying()
{
return ConfigurationManager.Configuration.MigrationVersion >= 1;
}
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
@ -196,21 +202,6 @@ namespace MediaBrowser.Controller.Entities
}
}
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
// Never want folders to be blocked by "BlockNotRated"
if (this is Series)
{
return base.OfficialRatingForComparison;
}
return !string.IsNullOrWhiteSpace(base.OfficialRatingForComparison) ? base.OfficialRatingForComparison : "None";
}
}
/// <summary>
/// Removes the child.
/// </summary>
@ -224,7 +215,12 @@ namespace MediaBrowser.Controller.Entities
item.SetParent(null);
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
if (!EnableNewFolderQuerying())
{
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
return Task.FromResult(true);
}
/// <summary>
@ -457,32 +453,25 @@ namespace MediaBrowser.Controller.Entities
{
BaseItem currentChild;
if (currentChildren.TryGetValue(child.Id, out currentChild))
if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child))
{
if (IsValidFromResolver(currentChild, child))
var currentChildLocationType = currentChild.LocationType;
if (currentChildLocationType != LocationType.Remote &&
currentChildLocationType != LocationType.Virtual)
{
var currentChildLocationType = currentChild.LocationType;
if (currentChildLocationType != LocationType.Remote &&
currentChildLocationType != LocationType.Virtual)
{
currentChild.DateModified = child.DateModified;
}
currentChild.DateModified = child.DateModified;
}
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
validChildren.Add(currentChild);
}
else
{
newItems.Add(child);
validChildren.Add(child);
}
}
else
{
// Brand new item - needs to be added
newItems.Add(child);
validChildren.Add(child);
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
validChildren.Add(currentChild);
continue;
}
// Brand new item - needs to be added
child.SetParent(this);
newItems.Add(child);
validChildren.Add(child);
}
// If any items were added or removed....
@ -508,7 +497,6 @@ namespace MediaBrowser.Controller.Entities
}
else
{
await UpdateIsOffline(item, false).ConfigureAwait(false);
actualRemovals.Add(item);
}
}
@ -519,6 +507,11 @@ namespace MediaBrowser.Controller.Entities
foreach (var item in actualRemovals)
{
Logger.Debug("Removed item: " + item.Path);
item.SetParent(null);
item.IsOffline = false;
await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false);
LibraryManager.ReportItemRemoved(item);
}
}
@ -527,7 +520,10 @@ namespace MediaBrowser.Controller.Entities
AddChildrenInternal(newItems);
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
}
}
@ -721,7 +717,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath);
return false;
}
/// <summary>
@ -757,19 +753,16 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns>
protected IEnumerable<BaseItem> GetCachedChildren()
{
if (ConfigurationManager.Configuration.DisableStartupScan)
if (EnableNewFolderQuerying())
{
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
//return ItemRepository.GetItems(new InternalItemsQuery
//{
// ParentId = Id
return ItemRepository.GetItemList(new InternalItemsQuery
{
ParentId = Id
//}).Items.Select(RetrieveChild).Where(i => i != null);
}
else
{
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
}).Select(RetrieveChild).Where(i => i != null);
}
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
}
private BaseItem RetrieveChild(BaseItem child)
@ -832,19 +825,7 @@ namespace MediaBrowser.Controller.Entities
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
}
/// <summary>
/// Gets allowed children of an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
return GetChildren(user, includeLinkedChildren, false);
}
internal IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, bool includeHidden)
{
if (user == null)
{
@ -856,7 +837,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>();
AddChildren(user, includeLinkedChildren, result, includeHidden, false, null);
AddChildren(user, includeLinkedChildren, result, false, null);
return result.Values;
}
@ -872,29 +853,25 @@ namespace MediaBrowser.Controller.Entities
/// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <param name="result">The result.</param>
/// <param name="includeHidden">if set to <c>true</c> [include hidden].</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="filter">The filter.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter)
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter)
{
foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
{
if (child.IsVisible(user))
{
if (includeHidden || !child.IsHiddenFromUser(user))
if (filter == null || filter(child))
{
if (filter == null || filter(child))
{
result[child.Id] = child;
}
result[child.Id] = child;
}
if (recursive && child.IsFolder)
{
var folder = (Folder)child;
folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter);
folder.AddChildren(user, includeLinkedChildren, result, true, filter);
}
}
}
@ -935,7 +912,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>();
AddChildren(user, true, result, false, true, filter);
AddChildren(user, true, result, true, filter);
return result.Values;
}
@ -1184,6 +1161,7 @@ namespace MediaBrowser.Controller.Entities
Recursive = true,
IsFolder = false,
IsUnaired = false
};
if (!user.Configuration.DisplayMissingEpisodes)
@ -1322,4 +1300,4 @@ namespace MediaBrowser.Controller.Entities
}
}
}
}
}

View file

@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
RemoteTrailerIds = new List<Guid>();
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
Tags = new List<string>();
}
public List<Guid> LocalTrailerIds { get; set; }
@ -34,12 +33,6 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual;
}
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
/// <summary>
/// Gets or sets the remote trailers.
/// </summary>
@ -105,9 +98,9 @@ namespace MediaBrowser.Controller.Entities
return base.GetDeletePaths();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Game);
return UnratedItem.Game;
}
public GameInfo GetLookupInfo()

View file

@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Game;
}
public GameSystemInfo GetLookupInfo()
{
var id = GetItemLookupInfo<GameSystemInfo>();

View file

@ -16,6 +16,11 @@ namespace MediaBrowser.Controller.Entities
IEnumerable<string> PhysicalLocations { get; }
}
public interface ISupportsUserSpecificView
{
bool EnableUserSpecificView { get; }
}
public static class CollectionFolderExtensions
{
public static string GetViewType(this ICollectionFolder folder, User user)

View 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);
}
}

View file

@ -1,6 +1,7 @@
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{
@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities
public string[] MediaTypes { get; set; }
public string[] IncludeItemTypes { get; set; }
public string[] ExcludeItemTypes { get; set; }
public string[] ExcludeTags { get; set; }
public string[] Genres { get; set; }
public bool? IsMissing { get; set; }
@ -69,12 +71,15 @@ namespace MediaBrowser.Controller.Entities
public string[] Studios { get; set; }
public string[] StudioIds { get; set; }
public string[] GenreIds { get; set; }
public ImageType[] ImageTypes { get; set; }
public VideoType[] VideoTypes { get; set; }
public UnratedItem[] BlockUnratedItems { get; set; }
public int[] Years { get; set; }
public string[] Tags { get; set; }
public string[] OfficialRatings { get; set; }
public DateTime? MinPremiereDate { get; set; }
public DateTime? MinStartDate { get; set; }
public DateTime? MaxStartDate { get; set; }
public DateTime? MinEndDate { get; set; }
@ -87,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
public int? MinPlayers { get; set; }
public int? MaxPlayers { get; set; }
public int? MinIndexNumber { get; set; }
public double? MinCriticRating { get; set; }
public double? MinCommunityRating { get; set; }
@ -101,9 +107,14 @@ namespace MediaBrowser.Controller.Entities
public LocationType? LocationType { get; set; }
public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; }
public InternalItemsQuery()
{
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { };
OfficialRatings = new string[] { };
SortBy = new string[] { };
@ -113,6 +124,7 @@ namespace MediaBrowser.Controller.Entities
Genres = new string[] { };
Studios = new string[] { };
StudioIds = new string[] { };
GenreIds = new string[] { };
ImageTypes = new ImageType[] { };
VideoTypes = new VideoType[] { };
Years = new int[] { };
@ -120,6 +132,29 @@ namespace MediaBrowser.Controller.Entities
PersonIds = new string[] { };
ChannelIds = new string[] { };
ItemIds = new string[] { };
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
ExcludeLocationTypes = new LocationType[] { };
}
public InternalItemsQuery(User user)
: this()
{
if (user != null)
{
var policy = user.Policy;
MaxParentalRating = policy.MaxParentalRating;
if (policy.MaxParentalRating.HasValue)
{
BlockUnratedItems = policy.BlockUnratedItems;
}
ExcludeTags = policy.BlockedTags;
User = user;
}
}
}
}

View file

@ -8,15 +8,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class BoxSet
/// </summary>
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
{
public List<Share> Shares { get; set; }
@ -65,6 +63,11 @@ namespace MediaBrowser.Controller.Entities.Movies
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Movie;
}
[IgnoreDataMember]
public override bool IsPreSorted
{
@ -154,34 +157,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return GetItemLookupInfo<BoxSetInfo>();
}
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
// Refresh bottom up, children first, then the boxset
// By then hopefully the movies within will have Tmdb collection values
var items = GetRecursiveChildren().ToList();
var totalItems = items.Count;
var numComplete = 0;
// Refresh songs
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= totalItems;
progress.Report(percent * 100);
}
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
public override bool IsVisible(User user)
{
var userId = user.Id.ToString("N");

View file

@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// Must have a parent to have special features
// In other words, it must be part of the Parent/Child tree
if (LocationType == LocationType.FileSystem && Parent != null && !IsInMixedFolder)
if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder)
{
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
@ -159,9 +159,9 @@ namespace MediaBrowser.Controller.Entities.Movies
return itemsChanged;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
return UnratedItem.Movie;
}
public MovieInfo GetLookupInfo()

View file

@ -56,9 +56,9 @@ namespace MediaBrowser.Controller.Entities
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
return UnratedItem.Music;
}
public MusicVideoInfo GetLookupInfo()

View file

@ -101,6 +101,15 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
[IgnoreDataMember]
public override bool SupportsAncestors
{
get
{
return false;
}
}
}
/// <summary>

View file

@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.Entities
{
public class Photo : BaseItem, IHasTags, IHasTaglines
{
public List<string> Tags { get; set; }
public List<string> Taglines { get; set; }
public Photo()
{
Tags = new List<string>();
Taglines = new List<string>();
}
@ -51,7 +49,7 @@ namespace MediaBrowser.Controller.Entities
{
get
{
return Parents.OfType<PhotoAlbum>().FirstOrDefault();
return GetParents().OfType<PhotoAlbum>().FirstOrDefault();
}
}
@ -70,10 +68,5 @@ namespace MediaBrowser.Controller.Entities
public double? Longitude { get; set; }
public double? Altitude { get; set; }
public int? IsoSpeedRating { get; set; }
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
}
}

View file

@ -9,8 +9,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
public class PhotoAlbum : Folder, IMetadataContainer
public class PhotoAlbum : Folder
{
[IgnoreDataMember]
public override bool SupportsLocalMetadata
{
get
@ -32,31 +33,5 @@ namespace MediaBrowser.Controller.Entities
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
var items = GetRecursiveChildren().ToList();
var totalItems = items.Count;
var numComplete = 0;
// Refresh songs
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= totalItems;
progress.Report(percent * 100);
}
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
}
}

View file

@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Studio : BaseItem, IItemByName, IHasTags
{
public List<string> Tags { get; set; }
public Studio()
{
Tags = new List<string>();
}
/// <summary>
/// Gets the user data key.
/// </summary>

View file

@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
return Season ?? Parent;
return Season ?? GetParent();
}
}
@ -115,19 +115,6 @@ namespace MediaBrowser.Controller.Entities.TV
return base.CreateUserDataKey();
}
/// <summary>
/// Our rating comes from our series
/// </summary>
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
var series = Series;
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
}
}
/// <summary>
/// This Episode's Series Instance
/// </summary>
@ -265,14 +252,28 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
public override IEnumerable<Guid> GetAncestorIds()
{
var list = base.GetAncestorIds().ToList();
var seasonId = SeasonId;
if (seasonId.HasValue && !list.Contains(seasonId.Value))
{
list.Add(seasonId.Value);
}
return list;
}
public override IEnumerable<string> GetDeletePaths()
{
return new[] { Path };
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
return UnratedItem.Series;
}
public EpisodeInfo GetLookupInfo()

View file

@ -6,6 +6,7 @@ using MoreLinq;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities.TV
{
@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public override BaseItem DisplayParent
{
get { return Series ?? Parent; }
get { return Series ?? GetParent(); }
}
// Genre, Rating and Stuido will all be the same
@ -87,19 +88,6 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
/// <summary>
/// Our rating comes from our series
/// </summary>
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
var series = Series;
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
}
}
/// <summary>
/// Creates the name of the sort.
/// </summary>
@ -234,6 +222,11 @@ namespace MediaBrowser.Controller.Entities.TV
return false;
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Series;
}
[IgnoreDataMember]
public string SeriesName
{

View file

@ -333,6 +333,11 @@ namespace MediaBrowser.Controller.Entities.TV
return config.BlockUnratedItems.Contains(UnratedItem.Series);
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Series;
}
public SeriesInfo GetLookupInfo()
{
var info = GetItemLookupInfo<SeriesInfo>();

View file

@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities
get
{
// Local trailers are not part of children
return Parent == null;
return GetParent() == null;
}
}
@ -97,9 +97,9 @@ namespace MediaBrowser.Controller.Entities
return base.CreateUserDataKey();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.Trailer);
return UnratedItem.Trailer;
}
public TrailerInfo GetLookupInfo()

View file

@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities
{
public static IUserManager UserManager { get; set; }
public static IXmlSerializer XmlSerializer { get; set; }
public bool EnableUserViews { get; set; }
/// <summary>
/// From now on all user paths will be Id-based.
@ -58,6 +57,26 @@ namespace MediaBrowser.Controller.Entities
}
}
private string _name;
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public override string Name
{
get
{
return _name;
}
set
{
_name = value;
// lazy load this again
SortName = null;
}
}
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself

View file

@ -55,13 +55,21 @@ namespace MediaBrowser.Controller.Entities
}
}
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList();
list.AddRange(LibraryManager.RootFolder.VirtualChildren);
return list;
}
/// <summary>
/// Get the children of this folder from the actual file system
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{
return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren);
return base.GetNonCachedChildren(directoryService);
}
public override bool BeforeMetadataRefresh()

View file

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using System.Linq;
namespace MediaBrowser.Controller.Entities
{
@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
public Guid DisplayParentId { get; set; }
public Guid? UserId { get; set; }
public static ITVSeriesManager TVSeriesManager;
public static IPlaylistManager PlaylistManager;
@ -24,7 +25,26 @@ namespace MediaBrowser.Controller.Entities
{
return true;
}
public override IEnumerable<Guid> GetIdsForAncestorQuery()
{
var list = new List<Guid>();
if (DisplayParentId != Guid.Empty)
{
list.Add(DisplayParentId);
}
else if (ParentId != Guid.Empty)
{
list.Add(ParentId);
}
else
{
list.Add(Id);
}
return list;
}
public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
var parent = this as Folder;
@ -81,16 +101,11 @@ namespace MediaBrowser.Controller.Entities
return GetChildren(user, false);
}
public static bool IsExcludedFromGrouping(Folder folder)
public static bool IsUserSpecific(Folder folder)
{
var standaloneTypes = new List<string>
{
CollectionType.Books,
CollectionType.HomeVideos,
CollectionType.Photos,
CollectionType.Playlists,
CollectionType.BoxSets,
CollectionType.MusicVideos
CollectionType.Playlists
};
var collectionFolder = folder as ICollectionFolder;
@ -100,25 +115,63 @@ namespace MediaBrowser.Controller.Entities
return false;
}
var supportsUserSpecific = folder as ISupportsUserSpecificView;
if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
{
return true;
}
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
}
public static bool IsUserSpecific(Folder folder)
public static bool IsEligibleForGrouping(Folder folder)
{
var standaloneTypes = new List<string>
{
CollectionType.Playlists,
var collectionFolder = folder as ICollectionFolder;
return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType);
}
public static bool IsEligibleForGrouping(string viewType)
{
var types = new[]
{
CollectionType.Movies,
CollectionType.TvShows,
string.Empty
};
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
public static bool IsEligibleForEnhancedView(string viewType)
{
var types = new[]
{
CollectionType.Movies,
CollectionType.TvShows
};
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
public static bool EnableOriginalFolder(string viewType)
{
var types = new[]
{
CollectionType.Games,
CollectionType.Books,
CollectionType.MusicVideos,
CollectionType.HomeVideos,
CollectionType.Photos,
CollectionType.Music,
CollectionType.BoxSets
};
var collectionFolder = folder as ICollectionFolder;
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
if (collectionFolder == null)
{
return false;
}
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService)
{
return Task.FromResult(true);
}
[IgnoreDataMember]

View file

@ -120,59 +120,34 @@ namespace MediaBrowser.Controller.Entities
return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
}
case CollectionType.Photos:
case CollectionType.Books:
case CollectionType.HomeVideos:
case CollectionType.Games:
case CollectionType.MusicVideos:
{
if (query.Recursive)
{
return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
}
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
case CollectionType.Folders:
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
case CollectionType.Games:
return await GetGameView(user, queryParent, query).ConfigureAwait(false);
case CollectionType.Playlists:
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.BoxSets:
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Photos:
return await GetPhotosView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.TvShows:
return await GetTvView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Music:
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Movies:
return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenres:
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenre:
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameGenres:
return await GetGameGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameGenre:
return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameSystems:
return GetGameSystems(queryParent, user, query);
case SpecialFolder.LatestGames:
return GetLatestGames(queryParent, user, query);
case SpecialFolder.RecentlyPlayedGames:
return GetRecentlyPlayedGames(queryParent, user, query);
case SpecialFolder.GameFavorites:
return GetFavoriteGames(queryParent, user, query);
case SpecialFolder.TvShowSeries:
return GetTvSeries(queryParent, user, query);
@ -212,6 +187,21 @@ namespace MediaBrowser.Controller.Entities
case SpecialFolder.MovieCollections:
return GetMovieCollections(queryParent, user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
case SpecialFolder.TvFavoriteSeries:
return GetFavoriteSeries(queryParent, user, query);
case CollectionType.Music:
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenres:
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenre:
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicLatest:
return GetMusicLatest(queryParent, user, query);
@ -230,12 +220,6 @@ namespace MediaBrowser.Controller.Entities
case SpecialFolder.MusicSongs:
return GetMusicSongs(queryParent, user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
case SpecialFolder.TvFavoriteSeries:
return GetFavoriteSeries(queryParent, user, query);
case SpecialFolder.MusicFavorites:
return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false);
@ -262,18 +246,6 @@ namespace MediaBrowser.Controller.Entities
}
}
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
{
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
return GetResult(list, parent, query);
}
private int GetSpecialItemsLimit()
{
return 50;
}
private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query)
{
if (query.Recursive)
@ -289,7 +261,7 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false));
//list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicArtists, "4", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false));
@ -422,6 +394,36 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
{
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
return GetResult(list, parent, query);
}
private int GetSpecialItemsLimit()
{
return 50;
}
private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
{
if (query.Recursive)
@ -480,24 +482,6 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query));
@ -617,54 +601,6 @@ namespace MediaBrowser.Controller.Entities
return GetResult(list, parent, query);
}
private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, InternalItemsQuery query)
{
if (query.Recursive)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
var list = new List<BaseItem>();
list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false));
return GetResult(list, parent, query);
}
private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, InternalItemsQuery query)
{
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query)
{
query.IsPlayed = true;
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
{
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
@ -745,49 +681,6 @@ namespace MediaBrowser.Controller.Entities
return GetResult(items, queryParent, query);
}
private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games },
i => i is Game && i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
return GetResult(items, queryParent, query);
}
private async Task<QueryResult<BaseItem>> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
{
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
.OfType<Game>()
.SelectMany(i => i.Genres)
.DistinctNames()
.Select(i =>
{
try
{
return _libraryManager.GetGameGenre(i);
}
catch
{
// Full exception logged at lower levels
_logger.Error("Error getting game genre");
return null;
}
})
.Where(i => i != null)
.Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent));
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
return GetResult(genres, parent, query);
}
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
where T : BaseItem
{
@ -1061,6 +954,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.GenreIds.Length > 0)
{
return false;
}
if (request.VideoTypes.Length > 0)
{
return false;
@ -1101,10 +999,15 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.MinIndexNumber.HasValue)
{
return false;
}
return true;
}
public static IEnumerable<BaseItem> FilterVirtualEpisodes(
private static IEnumerable<BaseItem> FilterVirtualEpisodes(
IEnumerable<BaseItem> items,
bool? isMissing,
bool? isVirtualUnaired,
@ -1374,7 +1277,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsInBoxSet.HasValue)
{
var val = query.IsInBoxSet.Value;
if (item.Parents.OfType<BoxSet>().Any() != val)
if (item.GetParents().OfType<BoxSet>().Any() != val)
{
return false;
}
@ -1657,6 +1560,16 @@ namespace MediaBrowser.Controller.Entities
return false;
}
// Apply genre filter
if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id =>
{
var genreItem = libraryManager.GetItemById(id);
return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase);
}))
{
return false;
}
// Apply year filter
if (query.Years.Length > 0)
{
@ -1779,6 +1692,16 @@ namespace MediaBrowser.Controller.Entities
}
}
if (query.MinIndexNumber.HasValue)
{
var val = query.MinIndexNumber.Value;
if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val))
{
return false;
}
}
return true;
}
@ -1789,12 +1712,12 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.RootFolder
.Children
.OfType<Folder>()
.Where(i => !UserView.IsExcludedFromGrouping(i));
.Where(UserView.IsEligibleForGrouping);
}
return user.RootFolder
.GetChildren(user, true, true)
.GetChildren(user, true)
.OfType<Folder>()
.Where(i => user.IsFolderGrouped(i.Id) && !UserView.IsExcludedFromGrouping(i));
.Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
}
private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)

View file

@ -185,12 +185,6 @@ namespace MediaBrowser.Controller.Entities
public bool IsShortcut { get; set; }
public string ShortcutPath { get; set; }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
/// <summary>
/// Gets or sets the video bit rate.
/// </summary>
@ -356,7 +350,7 @@ namespace MediaBrowser.Controller.Entities
// Must have a parent to have additional parts or alternate versions
// In other words, it must be part of the Parent/Child tree
// The additional parts won't have additional parts themselves
if (LocationType == LocationType.FileSystem && Parent != null)
if (LocationType == LocationType.FileSystem && GetParent() != null)
{
if (!IsStacked)
{

View file

@ -337,7 +337,6 @@ namespace MediaBrowser.Controller.Library
string parentId,
string viewType,
string sortName,
string uniqueId,
CancellationToken cancellationToken);
/// <summary>
@ -391,13 +390,11 @@ namespace MediaBrowser.Controller.Library
/// <param name="parent">The parent.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <param name="uniqueId">The unique identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;UserView&gt;.</returns>
Task<UserView> GetShadowView(BaseItem parent,
string viewType,
string sortName,
string uniqueId,
CancellationToken cancellationToken);
/// <summary>
@ -543,5 +540,29 @@ namespace MediaBrowser.Controller.Library
/// <param name="imageIndex">Index of the image.</param>
/// <returns>Task.</returns>
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>List&lt;BaseItem&gt;.</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&lt;BaseItem&gt;.</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);
}
}

View file

@ -155,7 +155,7 @@ namespace MediaBrowser.Controller.Library
// Not officially supported but in some cases we can handle it.
if (item == null)
{
item = parent.Parents.OfType<T>().FirstOrDefault();
item = parent.GetParents().OfType<T>().FirstOrDefault();
}
return item != null;

View file

@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsLive { get; set; }
[IgnoreDataMember]
public bool IsPremiere { get; set; }
public ProgramAudio? Audio { get; set; }
/// <summary>
/// Gets the user data key.
@ -106,9 +105,9 @@ namespace MediaBrowser.Controller.LiveTv
}
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
return UnratedItem.LiveTvProgram;
}
protected override string GetInternalMetadataPath(string basePath)
@ -140,5 +139,10 @@ namespace MediaBrowser.Controller.LiveTv
return list;
}
public override bool IsVisibleStandalone(User user)
{
return IsVisible(user);
}
}
}

View file

@ -22,9 +22,9 @@ namespace MediaBrowser.Controller.LiveTv
return GetClientTypeName() + "-" + Name;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel);
return UnratedItem.LiveTvChannel;
}
/// <summary>

View file

@ -40,10 +40,11 @@ namespace MediaBrowser.Controller.LiveTv
}
/// <summary>
/// Gets or sets the type of the channel.
/// Gets or sets the name.
/// </summary>
/// <value>The type of the channel.</value>
public ChannelType ChannelType { get; set; }
/// <value>The name.</value>
[IgnoreDataMember]
public string ServiceName { get; set; }
/// <summary>
/// The start date of the program, in UTC.
@ -51,12 +52,6 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public DateTime StartDate { get; set; }
/// <summary>
/// Gets or sets the audio.
/// </summary>
/// <value>The audio.</value>
public ProgramAudio? Audio { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is repeat.
/// </summary>
@ -71,12 +66,6 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public string EpisodeTitle { get; set; }
/// <summary>
/// Gets or sets the name of the service.
/// </summary>
/// <value>The name of the service.</value>
public string ServiceName { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is movie.
/// </summary>
@ -153,14 +142,14 @@ namespace MediaBrowser.Controller.LiveTv
}
}
[IgnoreDataMember]
public override string MediaType
{
get
{
return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
}
}
//[IgnoreDataMember]
//public override string MediaType
//{
// get
// {
// return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
// }
//}
[IgnoreDataMember]
public bool IsAiring
@ -189,9 +178,9 @@ namespace MediaBrowser.Controller.LiveTv
return "Program";
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
return UnratedItem.LiveTvProgram;
}
protected override string GetInternalMetadataPath(string basePath)
@ -236,5 +225,14 @@ namespace MediaBrowser.Controller.LiveTv
return base.SupportsPeople;
}
}
[IgnoreDataMember]
public override bool SupportsAncestors
{
get
{
return false;
}
}
}
}

View file

@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsLive { get; set; }
[IgnoreDataMember]
public bool IsPremiere { get; set; }
public ProgramAudio? Audio { get; set; }
/// <summary>
/// Gets the user data key.
@ -121,9 +120,9 @@ namespace MediaBrowser.Controller.LiveTv
}
}
protected override bool GetBlockUnratedValue(UserPolicy config)
public override UnratedItem GetBlockUnratedType()
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
return UnratedItem.LiveTvProgram;
}
protected override string GetInternalMetadataPath(string basePath)
@ -155,5 +154,10 @@ namespace MediaBrowser.Controller.LiveTv
return list;
}
public override bool IsVisibleStandalone(User user)
{
return IsVisible(user);
}
}
}

View file

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
@ -11,6 +12,11 @@ namespace MediaBrowser.Controller.LiveTv
return false;
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.LiveTvProgram;
}
public override bool SupportsLocalMetadata
{
get

View file

@ -162,6 +162,7 @@
<Compile Include="Entities\IHasThemeMedia.cs" />
<Compile Include="Entities\IHasTrailers.cs" />
<Compile Include="Entities\IHasUserData.cs" />
<Compile Include="Entities\IHiddenFromDisplay.cs" />
<Compile Include="Entities\IItemByName.cs" />
<Compile Include="Entities\ILibraryItem.cs" />
<Compile Include="Entities\ImageSourceInfo.cs" />

View file

@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Extracts the audio image.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="imageStreamIndex">Index of the image stream.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
/// <summary>
/// Extracts the video image.

View file

@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding
public IIsoMount MountedIso { get; set; }
public VideoType VideoType { get; set; }
public List<string> PlayableStreamFileNames { get; set; }
public bool ExtractKeyFrameInterval { get; set; }
public MediaInfoRequest()
{

View file

@ -176,6 +176,20 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;Tuple&lt;Guid, System.String&gt;&gt;.</returns>
QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
/// <summary>
/// Gets the item list.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;BaseItem&gt;.</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);
}
}

View file

@ -144,6 +144,7 @@ namespace MediaBrowser.Controller.Playlists
public string PlaylistMediaType { get; set; }
[IgnoreDataMember]
public override string MediaType
{
get

View file

@ -10,24 +10,6 @@ namespace MediaBrowser.Controller.Providers
/// <value>The item identifier.</value>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the name of the item.
/// </summary>
/// <value>The name of the item.</value>
public string ItemName { get; set; }
/// <summary>
/// Gets or sets the type of the item.
/// </summary>
/// <value>The type of the item.</value>
public string ItemType { get; set; }
/// <summary>
/// Gets or sets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
public string SeriesName { get; set; }
/// <summary>
/// Gets or sets the date last metadata refresh.
/// </summary>
@ -40,22 +22,8 @@ namespace MediaBrowser.Controller.Providers
/// <value>The date last images refresh.</value>
public DateTime? DateLastImagesRefresh { get; set; }
/// <summary>
/// Gets or sets the last result error message.
/// </summary>
/// <value>The last result error message.</value>
public string LastErrorMessage { get; set; }
public DateTime? ItemDateModified { get; set; }
public void AddStatus(string errorMessage)
{
if (string.IsNullOrEmpty(LastErrorMessage))
{
LastErrorMessage = errorMessage;
}
}
public bool IsDirty { get; private set; }
public void SetDateLastMetadataRefresh(DateTime? date)

View file

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Library;
using CommonIO;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Resolvers
{
@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers
/// </summary>
public interface IResolverIgnoreRule
{
bool ShouldIgnore(ItemResolveArgs args);
bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
}
}

View file

@ -26,6 +26,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly ILocalizationManager _localization;
private readonly IChannelManager _channelManager;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IUserViewManager _userViewManager;
public ContentDirectory(IDlnaManager dlna,
IUserDataManager userDataManager,
@ -34,7 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager)
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(logger, httpClient)
{
_dlna = dlna;
@ -46,6 +47,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_localization = localization;
_channelManager = channelManager;
_mediaSourceManager = mediaSourceManager;
_userViewManager = userViewManager;
}
private int SystemUpdateId
@ -86,7 +88,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
_config,
_localization,
_channelManager,
_mediaSourceManager)
_mediaSourceManager,
_userViewManager)
.ProcessControlRequest(request);
}

View file

@ -24,6 +24,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Model.Library;
namespace MediaBrowser.Dlna.ContentDirectory
{
@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly IUserDataManager _userDataManager;
private readonly IServerConfigurationManager _config;
private readonly User _user;
private readonly IUserViewManager _userViewManager;
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly DeviceProfile _profile;
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager)
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(config, logger)
{
_libraryManager = libraryManager;
@ -55,6 +57,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_user = user;
_systemUpdateId = systemUpdateId;
_channelManager = channelManager;
_userViewManager = userViewManager;
_profile = profile;
_config = config;
@ -450,16 +453,32 @@ namespace MediaBrowser.Dlna.ContentDirectory
sortOrders.Add(ItemSortBy.SortName);
}
var queryResult = await folder.GetItems(new InternalItemsQuery
{
Limit = limit,
StartIndex = startIndex,
SortBy = sortOrders.ToArray(),
SortOrder = sort.SortOrder,
User = user,
Filter = FilterUnsupportedContent
QueryResult<BaseItem> queryResult;
}).ConfigureAwait(false);
if (folder is UserRootFolder)
{
var views = await _userViewManager.GetUserViews(new UserViewQuery { UserId = user.Id.ToString("N"), PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music } }, CancellationToken.None)
.ConfigureAwait(false);
queryResult = new QueryResult<BaseItem>
{
Items = views.Cast<BaseItem>().ToArray()
};
queryResult.TotalRecordCount = queryResult.Items.Length;
}
else
{
queryResult = await folder.GetItems(new InternalItemsQuery
{
Limit = limit,
StartIndex = startIndex,
SortBy = sortOrders.ToArray(),
SortOrder = sort.SortOrder,
User = user,
Filter = FilterUnsupportedContent
}).ConfigureAwait(false);
}
var options = _config.GetDlnaConfiguration();
@ -481,23 +500,17 @@ namespace MediaBrowser.Dlna.ContentDirectory
private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
{
var itemsWithPerson = _libraryManager.GetItems(new InternalItemsQuery
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
Person = person.Name
Person = person.Name,
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name },
SortBy = new[] { ItemSortBy.SortName },
Limit = limit,
StartIndex = startIndex
}).Items;
}, new string[] { });
var items = itemsWithPerson
.Where(i => i is Movie || i is Series || i is IChannelItem)
.Where(i => i.IsVisibleStandalone(user))
.ToList();
items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
.Skip(startIndex ?? 0)
.Take(limit ?? int.MaxValue)
.ToList();
var serverItems = items.Select(i => new ServerItem
var serverItems = itemsResult.Items.Select(i => new ServerItem
{
Item = i,
StubType = null
@ -506,7 +519,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return new QueryResult<ServerItem>
{
TotalRecordCount = serverItems.Length,
TotalRecordCount = itemsResult.TotalRecordCount,
Items = serverItems
};
}

View file

@ -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)
{

View file

@ -79,14 +79,11 @@
<Compile Include="Providers\SeriesXmlProvider.cs" />
<Compile Include="Providers\VideoXmlProvider.cs" />
<Compile Include="Savers\BoxSetXmlSaver.cs" />
<Compile Include="Savers\EpisodeXmlSaver.cs" />
<Compile Include="Savers\FolderXmlSaver.cs" />
<Compile Include="Savers\GameSystemXmlSaver.cs" />
<Compile Include="Savers\GameXmlSaver.cs" />
<Compile Include="Savers\MovieXmlSaver.cs" />
<Compile Include="Savers\PersonXmlSaver.cs" />
<Compile Include="Savers\PlaylistXmlSaver.cs" />
<Compile Include="Savers\SeriesXmlSaver.cs" />
<Compile Include="Savers\XmlSaverHelpers.cs" />
</ItemGroup>
<ItemGroup>

View file

@ -1,166 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
using CommonIO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
public class EpisodeXmlProvider : IMetadataFileSaver, IConfigurableProvider
{
private readonly IItemRepository _itemRepository;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private IFileSystem _fileSystem;
public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_itemRepository = itemRepository;
_config = config;
_libraryManager = libraryManager;
_fileSystem = fileSystem;
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
return false;
}
return item is Episode && updateType >= ItemUpdateType.MetadataDownload;
}
public string Name
{
get
{
return XmlProviderUtils.Name;
}
}
public bool IsEnabled
{
get { return !_config.Configuration.DisableXmlSavers; }
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var episode = (Episode)item;
var builder = new StringBuilder();
builder.Append("<Item>");
if (!string.IsNullOrEmpty(item.Name))
{
builder.Append("<EpisodeName>" + SecurityElement.Escape(episode.Name) + "</EpisodeName>");
}
if (episode.IndexNumber.HasValue)
{
builder.Append("<EpisodeNumber>" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + "</EpisodeNumber>");
}
if (episode.IndexNumberEnd.HasValue)
{
builder.Append("<EpisodeNumberEnd>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</EpisodeNumberEnd>");
}
if (episode.AirsAfterSeasonNumber.HasValue)
{
builder.Append("<airsafter_season>" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "</airsafter_season>");
}
if (episode.AirsBeforeEpisodeNumber.HasValue)
{
builder.Append("<airsbefore_episode>" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "</airsbefore_episode>");
}
if (episode.AirsBeforeSeasonNumber.HasValue)
{
builder.Append("<airsbefore_season>" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "</airsbefore_season>");
}
if (episode.ParentIndexNumber.HasValue)
{
builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>");
}
if (episode.AbsoluteEpisodeNumber.HasValue)
{
builder.Append("<absolute_number>" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "</absolute_number>");
}
if (episode.DvdEpisodeNumber.HasValue)
{
builder.Append("<DVD_episodenumber>" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "</DVD_episodenumber>");
}
if (episode.DvdSeasonNumber.HasValue)
{
builder.Append("<DVD_season>" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "</DVD_season>");
}
if (episode.PremiereDate.HasValue)
{
builder.Append("<FirstAired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
}
XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder);
XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"FirstAired",
"SeasonNumber",
"EpisodeNumber",
"EpisodeName",
"EpisodeNumberEnd",
"airsafter_season",
"airsbefore_episode",
"airsbefore_season",
"DVD_episodenumber",
"DVD_season",
"absolute_number"
}, _config, _fileSystem);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(IHasMetadata item)
{
var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml");
return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename);
}
}
}

View file

@ -1,147 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
using CommonIO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Saves movie.xml for movies, trailers and music videos
/// </summary>
public class MovieXmlProvider : IMetadataFileSaver, IConfigurableProvider
{
private readonly IItemRepository _itemRepository;
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private IFileSystem _fileSystem;
public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_itemRepository = itemRepository;
_config = config;
_libraryManager = libraryManager;
_fileSystem = fileSystem;
}
public string Name
{
get
{
return XmlProviderUtils.Name;
}
}
public bool IsEnabled
{
get { return !_config.Configuration.DisableXmlSavers; }
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
return false;
}
var video = item as Video;
// Check parent for null to avoid running this against things like video backdrops
if (video != null && !(item is Episode) && !video.IsOwnedItem)
{
return updateType >= ItemUpdateType.MetadataDownload;
}
return false;
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var video = (Video)item;
var builder = new StringBuilder();
builder.Append("<Title>");
XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder);
var musicVideo = item as MusicVideo;
if (musicVideo != null)
{
if (musicVideo.Artists.Count > 0)
{
builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>");
}
if (!string.IsNullOrEmpty(musicVideo.Album))
{
builder.Append("<Album>" + SecurityElement.Escape(musicVideo.Album) + "</Album>");
}
}
var movie = item as Movie;
if (movie != null)
{
if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
{
builder.Append("<TmdbCollectionName>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</TmdbCollectionName>");
}
}
XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository);
builder.Append("</Title>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
// Deprecated. No longer saving in this field.
"IMDBrating",
// Deprecated. No longer saving in this field.
"Description",
"Artist",
"Album",
"TmdbCollectionName"
}, _config, _fileSystem);
}
public string GetSavePath(IHasMetadata item)
{
return GetMovieSavePath((Video)item);
}
public static string GetMovieSavePath(Video item)
{
if (item.IsInMixedFolder)
{
return Path.ChangeExtension(item.Path, ".xml");
}
return Path.Combine(item.ContainingFolderPath, "movie.xml");
}
}
}

View file

@ -1,154 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
using CommonIO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
public class SeriesXmlProvider : IMetadataFileSaver, IConfigurableProvider
{
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private IFileSystem _fileSystem;
public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
_fileSystem = fileSystem;
}
public string Name
{
get
{
return XmlProviderUtils.Name;
}
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
return false;
}
return item is Series && updateType >= ItemUpdateType.MetadataDownload;
}
public bool IsEnabled
{
get { return !_config.Configuration.DisableXmlSavers; }
}
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var series = (Series)item;
var builder = new StringBuilder();
builder.Append("<Series>");
var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(tvdb))
{
builder.Append("<id>" + SecurityElement.Escape(tvdb) + "</id>");
}
if (series.Status.HasValue)
{
builder.Append("<Status>" + SecurityElement.Escape(series.Status.Value.ToString()) + "</Status>");
}
if (series.Studios.Count > 0)
{
builder.Append("<Network>" + SecurityElement.Escape(series.Studios[0]) + "</Network>");
}
if (!string.IsNullOrEmpty(series.AirTime))
{
builder.Append("<Airs_Time>" + SecurityElement.Escape(series.AirTime) + "</Airs_Time>");
}
if (series.AirDays != null)
{
if (series.AirDays.Count == 7)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape("Daily") + "</Airs_DayOfWeek>");
}
else if (series.AirDays.Count > 0)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
}
}
if (series.PremiereDate.HasValue)
{
builder.Append("<FirstAired>" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
}
if (series.AnimeSeriesIndex.HasValue)
{
builder.Append("<AnimeSeriesIndex>" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "</AnimeSeriesIndex>");
}
XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder);
builder.Append("</Series>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"id",
"Status",
"Network",
"Airs_Time",
"Airs_DayOfWeek",
"FirstAired",
// Don't preserve old series node
"Series",
"SeriesName",
// Deprecated. No longer saving in this field.
"AnimeSeriesIndex"
}, _config, _fileSystem);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(IHasMetadata item)
{
return Path.Combine(item.Path, "series.xml");
}
}
}

View file

@ -472,18 +472,18 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// </summary>
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
public Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
{
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken);
}
public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat,
TimeSpan? offset, CancellationToken cancellationToken)
{
return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken);
return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken);
}
private async Task<Stream> ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio,
private async Task<Stream> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{
var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@ -494,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
try
{
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
}
catch (ArgumentException)
{
@ -506,10 +506,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
}
private async Task<Stream> ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
private async Task<Stream> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{

View file

@ -141,6 +141,7 @@ namespace MediaBrowser.MediaEncoding.Probing
if (streamInfo.tags != null)
{
stream.Language = GetDictionaryValue(streamInfo.tags, "language");
stream.Comment = GetDictionaryValue(streamInfo.tags, "comment");
}
if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))

View file

@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
.ConfigureAwait(false);
var inputFormat = subtitle.Item2;
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
{
return subtitle.Item1;
}
using (var stream = subtitle.Item1)
{
var inputFormat = subtitle.Item2;
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
}
}
@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return null;
}
private ISubtitleWriter GetWriter(string format)
private ISubtitleWriter TryGetWriter(string format)
{
if (string.IsNullOrEmpty(format))
{
@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return new TtmlWriter();
}
return null;
}
private ISubtitleWriter GetWriter(string format)
{
var writer = TryGetWriter(format);
if (writer != null)
{
return writer;
}
throw new ArgumentException("Unsupported format: " + format);
}

View file

@ -11,16 +11,19 @@ namespace MediaBrowser.Model.Configuration
public bool EnableIntrosParentalControl { get; set; }
public bool EnableIntrosFromSimilarMovies { get; set; }
public string CustomIntroPath { get; set; }
public string MediaInfoIntroPath { get; set; }
public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
public int TrailerLimit { get; set; }
public string[] Tags { get; set; }
public CinemaModeConfiguration()
{
EnableIntrosParentalControl = true;
EnableIntrosFromSimilarMovies = true;
TrailerLimit = 2;
Tags = new[] { "thx" };
}
}
}

View file

@ -62,6 +62,12 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if this instance is port authorized; otherwise, <c>false</c>.</value>
public bool IsPortAuthorized { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable high quality image scaling].
/// </summary>
/// <value><c>true</c> if [enable high quality image scaling]; otherwise, <c>false</c>.</value>
public bool EnableHighQualityImageScaling { get; set; }
/// <summary>
/// Gets or sets the item by name path.
/// </summary>
@ -92,24 +98,6 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
public bool EnableLocalizedGuids { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [disable startup scan].
/// </summary>
/// <value><c>true</c> if [disable startup scan]; otherwise, <c>false</c>.</value>
public bool DisableStartupScan { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable user views].
/// </summary>
/// <value><c>true</c> if [enable user views]; otherwise, <c>false</c>.</value>
public bool EnableUserViews { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable library metadata sub folder].
/// </summary>
/// <value><c>true</c> if [enable library metadata sub folder]; otherwise, <c>false</c>.</value>
public bool EnableLibraryMetadataSubFolder { get; set; }
/// <summary>
/// Gets or sets the preferred metadata language.
/// </summary>
@ -219,21 +207,20 @@ namespace MediaBrowser.Model.Configuration
public int SharingExpirationDays { get; set; }
public bool DisableXmlSavers { get; set; }
public bool EnableWindowsShortcuts { get; set; }
public bool EnableVideoFrameByFrameAnalysis { get; set; }
public bool EnableDateLastRefresh { get; set; }
public string[] Migrations { get; set; }
public int MigrationVersion { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>
public ServerConfiguration()
{
Migrations = new string[] {};
Migrations = new string[] { };
ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096;
@ -578,7 +565,7 @@ namespace MediaBrowser.Model.Configuration
Type = ImageType.Thumb
}
},
DisabledMetadataFetchers = new []{ "TheMovieDb" }
DisabledMetadataFetchers = new []{ "The Open Movie Database", "TheMovieDb" }
},
new MetadataOptions(0, 1280)
@ -599,6 +586,7 @@ namespace MediaBrowser.Model.Configuration
Type = ImageType.Primary
}
},
DisabledMetadataFetchers = new []{ "The Open Movie Database" },
DisabledImageFetchers = new []{ "TheMovieDb" }
}
};

View file

@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities
/// <value>The language.</value>
public string Language { get; set; }
/// <summary>
/// Gets or sets the comment.
/// </summary>
/// <value>The comment.</value>
public string Comment { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is interlaced.
/// </summary>

View file

@ -1038,7 +1038,7 @@ namespace MediaBrowser.Providers.Manager
.ToList();
var musicArtists = albums
.Select(i => i.Parent)
.Select(i => i.GetParent())
.OfType<MusicArtist>()
.ToList();

View file

@ -177,6 +177,7 @@
<Compile Include="TV\MovieDbSeasonProvider.cs" />
<Compile Include="TV\MovieDbSeriesImageProvider.cs" />
<Compile Include="TV\MovieDbSeriesProvider.cs" />
<Compile Include="TV\OmdbEpisodeProvider.cs" />
<Compile Include="TV\SeriesMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
<Compile Include="People\TvdbPersonImageProvider.cs" />

View file

@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
using System;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@ -43,20 +44,27 @@ namespace MediaBrowser.Providers.MediaInfo
{
var audio = (Audio)item;
var imageStreams =
audio.GetMediaSources(false)
.Take(1)
.SelectMany(i => i.MediaStreams)
.Where(i => i.Type == MediaStreamType.EmbeddedImage)
.ToList();
// Can't extract if we didn't find a video stream in the file
if (!audio.GetMediaSources(false).Take(1).SelectMany(i => i.MediaStreams).Any(i => i.Type == MediaStreamType.EmbeddedImage))
if (imageStreams.Count == 0)
{
return Task.FromResult(new DynamicImageResponse { HasImage = false });
}
return GetImage((Audio)item, cancellationToken);
return GetImage((Audio)item, imageStreams, cancellationToken);
}
public async Task<DynamicImageResponse> GetImage(Audio item, CancellationToken cancellationToken)
public async Task<DynamicImageResponse> GetImage(Audio item, List<MediaStream> imageStreams, CancellationToken cancellationToken)
{
var path = GetAudioImagePath(item);
if (!_fileSystem.FileExists(path))
if (!_fileSystem.FileExists(path))
{
var semaphore = GetLock(path);
@ -66,11 +74,16 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
// Check again in case it was saved while waiting for the lock
if (!_fileSystem.FileExists(path))
if (!_fileSystem.FileExists(path))
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1);
var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false))
{
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{

View file

@ -60,12 +60,18 @@ namespace MediaBrowser.Providers.Omdb
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken)
{
bool isSearch = false;
var episodeSearchInfo = searchInfo as EpisodeInfo;
var list = new List<RemoteSearchResult>();
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 year = searchInfo.Year;
@ -95,6 +101,18 @@ namespace MediaBrowser.Providers.Omdb
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
{
Url = url,
@ -124,10 +142,20 @@ namespace MediaBrowser.Providers.Omdb
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);
int parsedYear;
@ -137,6 +165,13 @@ namespace MediaBrowser.Providers.Omdb
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))
{
item.ImageUrl = result.Poster;
@ -267,6 +302,8 @@ namespace MediaBrowser.Providers.Omdb
public string Year { get; set; }
public string Rated { get; set; }
public string Released { get; set; }
public string Season { get; set; }
public string Episode { get; set; }
public string Runtime { get; set; }
public string Genre { get; set; }
public string Director { get; set; }
@ -281,6 +318,7 @@ namespace MediaBrowser.Providers.Omdb
public string imdbRating { get; set; }
public string imdbVotes { get; set; }
public string imdbID { get; set; }
public string seriesID { get; set; }
public string Type { get; set; }
public string Response { get; set; }
}

View 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);
}
}
}

View file

@ -104,6 +104,11 @@ namespace MediaBrowser.Server.Implementations.Channels
.OrderBy(i => i.Name);
}
public IEnumerable<Guid> GetInstalledChannelIds()
{
return GetAllChannels().Select(i => GetInternalChannelId(i.Name));
}
public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrWhiteSpace(query.UserId)
@ -408,25 +413,15 @@ namespace MediaBrowser.Server.Implementations.Channels
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 path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
var isNew = false;
if (!_fileSystem.DirectoryExists(path))
{
_logger.Debug("Creating directory {0}", path);
_fileSystem.CreateDirectory(path);
if (!_fileSystem.DirectoryExists(path))
{
throw new IOException("Path not created: " + path);
}
isNew = true;
}
var forceUpdate = false;
var item = _libraryManager.GetItemById(id) as Channel;
var channelId = channelInfo.Name.GetMD5().ToString("N");
@ -438,18 +433,29 @@ namespace MediaBrowser.Server.Implementations.Channels
Name = channelInfo.Name,
Id = id,
DateCreated = _fileSystem.GetCreationTimeUtc(path),
DateModified = _fileSystem.GetLastWriteTimeUtc(path),
Path = path,
ChannelId = channelId
DateModified = _fileSystem.GetLastWriteTimeUtc(path)
};
isNew = true;
}
if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
isNew = true;
}
item.Path = path;
if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
{
forceUpdate = true;
}
item.ChannelId = channelId;
if (item.ParentId != parentFolderId)
{
forceUpdate = true;
}
item.ParentId = parentFolderId;
item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
item.Overview = channelInfo.Description;
@ -459,13 +465,17 @@ namespace MediaBrowser.Server.Implementations.Channels
{
item.Name = channelInfo.Name;
}
await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
if (isNew)
{
ForceSave = isNew
}, cancellationToken);
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
}
else if (forceUpdate)
{
await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
}
await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken);
return item;
}
@ -1225,6 +1235,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
BaseItem item;
bool isNew;
bool forceUpdate = false;
if (info.Type == ChannelItemType.Folder)
{
@ -1254,25 +1265,26 @@ namespace MediaBrowser.Server.Implementations.Channels
item.ProductionYear = info.ProductionYear;
item.ProviderIds = info.ProviderIds;
item.OfficialRating = info.OfficialRating;
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
item.Tags = info.Tags;
}
var channelItem = (IChannelItem)item;
channelItem.ChannelId = internalChannelId.ToString("N");
if (item.ParentId != internalChannelId)
{
forceUpdate = true;
}
item.ParentId = internalChannelId;
if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
{
isNew = true;
forceUpdate = true;
}
channelItem.ExternalId = info.Id;
if (isNew)
{
channelItem.Tags = info.Tags;
}
var channelMediaItem = item as IChannelMediaItem;
if (channelMediaItem != null)
@ -1300,6 +1312,10 @@ namespace MediaBrowser.Server.Implementations.Channels
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
}
}
else if (forceUpdate)
{
await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
}
return item;
}
@ -1573,4 +1589,4 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
}
}
}

View file

@ -123,15 +123,15 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task CleanDatabase(CancellationToken cancellationToken)
{
var allChannels = await _channelManager.GetChannelsInternal(new ChannelQuery { }, cancellationToken);
var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Channel).Name }
});
var invalidIds = allIds
.Except(allChannels.Items.Select(i => i.Id).ToList())
var invalidIds = databaseIds
.Except(installedChannelIds)
.ToList();
foreach (var id in invalidIds)

View file

@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Collections
return subItem;
}
var parent = subItem.Parent;
var parent = subItem.GetParent();
if (parent != null && parent.HasImage(ImageType.Primary))
{
@ -78,24 +78,9 @@ namespace MediaBrowser.Server.Implementations.Collections
return Task.FromResult(GetFinalItems(items, 2));
}
protected override async Task<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
.Where(i => i.HasImage(ImageType.Primary) && i.GetImageInfo(ImageType.Primary, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(ImageType.Primary)))
.Select(i => i.GetImagePath(ImageType.Primary))
.FirstOrDefault();
if (string.IsNullOrWhiteSpace(image))
{
return null;
}
var ext = Path.GetExtension(image);
var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext);
File.Copy(image, outputPath);
return outputPath;
return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary);
}
}
}

View file

@ -40,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public Folder GetCollectionsFolder(string userId)
{
return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>()
.FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType<ManualCollectionsFolder>()
.FirstOrDefault();
}

View file

@ -3,7 +3,7 @@ using System.Linq;
namespace MediaBrowser.Server.Implementations.Collections
{
public class ManualCollectionsFolder : BasePluginFolder
public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay
{
public ManualCollectionsFolder()
{
@ -11,11 +11,6 @@ namespace MediaBrowser.Server.Implementations.Collections
DisplayMediaType = "CollectionFolder";
}
public override bool IsVisible(User user)
{
return base.IsVisible(user) && GetChildren(user, false).Any();
}
public override bool IsHidden
{
get
@ -24,7 +19,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
public override bool IsHiddenFromUser(User user)
public bool IsHiddenFromUser(User user)
{
return !user.Configuration.DisplayCollectionsView;
}
@ -36,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public override string GetClientTypeName()
{
return typeof (CollectionFolder).Name;
return typeof(CollectionFolder).Name;
}
}
}

View file

@ -171,12 +171,36 @@ namespace MediaBrowser.Server.Implementations.Configuration
ValidateItemByNamePath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
ValidateSslCertificate(newConfig);
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
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)
{
foreach (var map in newConfig.PathSubstitutions)

View file

@ -3,12 +3,15 @@ using MediaBrowser.Controller.Entities;
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Server.Implementations.Devices
{
public class CameraUploadsFolder : BasePluginFolder
public class CameraUploadsFolder : BasePluginFolder, ISupportsUserSpecificView
{
public CameraUploadsFolder()
{
@ -21,22 +24,8 @@ namespace MediaBrowser.Server.Implementations.Devices
{
return false;
}
return GetChildren(user, true).Any() &&
base.IsVisible(user);
}
public override bool IsHidden
{
get
{
return base.IsHidden || !Children.Any();
}
}
public override bool IsHiddenFromUser(User user)
{
return false;
return base.IsVisible(user) && HasChildren();
}
public override string CollectionType
@ -48,6 +37,29 @@ namespace MediaBrowser.Server.Implementations.Devices
{
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
@ -65,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Devices
{
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
_fileSystem.CreateDirectory(path);
_fileSystem.CreateDirectory(path);
return new CameraUploadsFolder
{

View file

@ -1,6 +1,5 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
@ -18,6 +17,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Configuration;
namespace MediaBrowser.Server.Implementations.Devices
{
@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.Devices
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IConfigurationManager _config;
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly INetworkManager _network;
@ -38,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Devices
/// </summary>
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;
_userManager = userManager;
@ -187,11 +187,6 @@ namespace MediaBrowser.Server.Implementations.Devices
}
}
private string GetUploadPath(string deviceId)
{
return GetUploadPath(GetDevice(deviceId));
}
private string GetUploadPath(DeviceInfo device)
{
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
@ -205,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Devices
return config.CameraUploadPath;
}
var path = Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads");
var path = DefaultCameraUploadsPath;
if (config.EnableCameraUploadSubfolders)
{
@ -215,6 +210,11 @@ namespace MediaBrowser.Server.Implementations.Devices
return path;
}
private string DefaultCameraUploadsPath
{
get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
}
public async Task UpdateDeviceInfo(string id, DeviceOptions options)
{
var device = GetDevice(id);

View file

@ -163,16 +163,11 @@ namespace MediaBrowser.Server.Implementations.Dto
if (person != null)
{
var items = _libraryManager.GetItems(new InternalItemsQuery
var items = _libraryManager.GetItems(new InternalItemsQuery(user)
{
Person = byName.Name
}).Items;
if (user != null)
{
return items.Where(i => i.IsVisibleStandalone(user)).ToList();
}
}, new string[] { });
return items.ToList();
}
@ -361,6 +356,8 @@ namespace MediaBrowser.Server.Implementations.Dto
var collectionFolder = item as ICollectionFolder;
if (collectionFolder != null)
{
dto.OriginalCollectionType = collectionFolder.CollectionType;
dto.CollectionType = user == null ?
collectionFolder.CollectionType :
collectionFolder.GetViewType(user);
@ -468,13 +465,15 @@ namespace MediaBrowser.Server.Implementations.Dto
var folder = (Folder)item;
dto.ChildCount = GetChildCount(folder, user);
// These are just far too slow.
// TODO: Disable for CollectionFolder
if (!(folder is UserRootFolder) && !(folder is UserView))
if (!(folder is IChannelItem) && !(folder is Channel))
{
SetSpecialCounts(folder, user, dto, fields, syncProgress);
dto.ChildCount = GetChildCount(folder, user);
// These are just far too slow.
if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is ICollectionFolder))
{
SetSpecialCounts(folder, user, dto, fields, syncProgress);
}
}
dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
@ -815,7 +814,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// <returns>BaseItem.</returns>
private BaseItem GetParentBackdropItem(BaseItem item, BaseItem owner)
{
var parent = item.Parent ?? owner;
var parent = item.GetParent() ?? owner;
while (parent != null)
{
@ -824,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
parent = parent.Parent;
parent = parent.GetParent();
}
return null;
@ -839,7 +838,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// <returns>BaseItem.</returns>
private BaseItem GetParentImageItem(BaseItem item, ImageType type, BaseItem owner)
{
var parent = item.Parent ?? owner;
var parent = item.GetParent() ?? owner;
while (parent != null)
{
@ -848,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
parent = parent.Parent;
parent = parent.GetParent();
}
return null;
@ -1042,7 +1041,11 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.IsFolder = item.IsFolder;
dto.MediaType = item.MediaType;
dto.LocationType = item.LocationType;
dto.IsHD = item.IsHD;
if (item.IsHD.HasValue && item.IsHD.Value)
{
dto.IsHD = item.IsHD;
}
dto.Audio = item.Audio;
dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode;
dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage;
@ -1209,15 +1212,15 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.VoteCount = item.VoteCount;
}
if (item.IsFolder)
{
var folder = (Folder)item;
//if (item.IsFolder)
//{
// var folder = (Folder)item;
if (fields.Contains(ItemFields.IndexOptions))
{
dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
}
}
// if (fields.Contains(ItemFields.IndexOptions))
// {
// dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
// }
//}
var supportsPlaceHolders = item as ISupportsPlaceHolders;
if (supportsPlaceHolders != null)
@ -1520,7 +1523,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.ChannelId = item.ChannelId;
var channelItem = item as IChannelItem;
if (channelItem != null)
{

View file

@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// Go up one level for indicators
if (baseItem != null)
{
var parent = baseItem.Parent;
var parent = baseItem.GetParent();
if (parent != null)
{

View file

@ -427,11 +427,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}, cancellationToken).ConfigureAwait(false);
var episode = searchResults.FirstOrDefault();
string episodeName = string.Empty;
if (episode == null)
{
_logger.Warn("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
return null;
var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
_logger.Warn(msg);
//throw new Exception(msg);
}
else
{
episodeName = episode.Name;
}
var newPath = GetSeasonFolderPath(series, seasonNumber, options);
@ -449,7 +456,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
// Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt)
maxFilenameLength -= 4;
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options, maxFilenameLength);
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episodeName, options, maxFilenameLength);
if (string.IsNullOrEmpty(episodeFileName))
{
@ -505,7 +512,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
if (episodeTitle == null)
if (string.IsNullOrEmpty(episodeTitle))
{
episodeTitle = string.Empty;
}

View file

@ -217,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
if (e.Item.Parent is AggregateFolder)
if (e.Item.GetParent() is AggregateFolder)
{
StopWatchingPath(e.Item.Path);
}
@ -230,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
if (e.Item.Parent is AggregateFolder)
if (e.Item.GetParent() is AggregateFolder)
{
StartWatchingPath(e.Item.Path);
}
@ -536,9 +536,16 @@ namespace MediaBrowser.Server.Implementations.IO
return false;
}
// In order to determine if the file is being written to, we have to request write access
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
// So we'll take a best guess about our access level
var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
? FileAccess.ReadWrite
: FileAccess.Read;
try
{
using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite))
{
if (_updateTimer != null)
{
@ -655,7 +662,7 @@ namespace MediaBrowser.Server.Implementations.IO
// If the item has been deleted find the first valid parent that still exists
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
{
item = item.Parent;
item = item.GetParent();
if (item == null)
{

View file

@ -78,13 +78,11 @@ namespace MediaBrowser.Server.Implementations.Intros
if (config.EnableIntrosFromMoviesInLibrary)
{
var inputItems = _libraryManager.GetItems(new InternalItemsQuery
var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name },
IncludeItemTypes = new[] { typeof(Movie).Name }
User = user
}).Items;
}, new string[]{});
var itemsWithTrailers = inputItems
.Where(i =>
@ -163,7 +161,7 @@ namespace MediaBrowser.Server.Implementations.Intros
private IEnumerable<IntroInfo> GetResult(BaseItem item, IEnumerable<ItemWithTrailer> candidates, CinemaModeConfiguration config, int? ratingLevel)
{
var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?
GetCustomIntros(item) :
GetCustomIntros(config) :
new List<IntroInfo>();
var trailerLimit = config.TrailerLimit;
@ -212,11 +210,11 @@ namespace MediaBrowser.Server.Implementations.Intros
return _serverConfig.GetConfiguration<CinemaModeConfiguration>("cinemamode");
}
private List<IntroInfo> GetCustomIntros(BaseItem item)
private List<IntroInfo> GetCustomIntros(CinemaModeConfiguration options)
{
try
{
return GetCustomIntroFiles()
return GetCustomIntroFiles(options, true, false)
.OrderBy(i => Guid.NewGuid())
.Select(i => new IntroInfo
{
@ -230,17 +228,23 @@ namespace MediaBrowser.Server.Implementations.Intros
}
}
private IEnumerable<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)
.Where(_libraryManager.IsVideoFile);
if (enableMediaInfoIntros && !string.IsNullOrWhiteSpace(options.MediaInfoIntroPath))
{
list.AddRange(_fileSystem.GetFilePaths(options.MediaInfoIntroPath, true)
.Where(_libraryManager.IsVideoFile));
}
return list.Distinct(StringComparer.OrdinalIgnoreCase);
}
private bool FilterByParentalRating(int? ratingLevel, BaseItem item)
@ -341,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Intros
public IEnumerable<string> GetAllIntroFiles()
{
return GetCustomIntroFiles();
return GetCustomIntroFiles(GetOptions(), true, true);
}
private bool IsSupporter

View file

@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library
/// <summary>
/// Shoulds the ignore.
/// </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>
public bool ShouldIgnore(ItemResolveArgs args)
public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
{
var filename = args.FileInfo.Name;
var filename = fileInfo.Name;
var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
var path = fileInfo.FullName;
// Handle mac .DS_Store
// https://github.com/MediaBrowser/MediaBrowser/issues/427
@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library
}
// Ignore hidden files and folders
if (args.IsHidden)
if (isHidden)
{
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path));
if (parent == null)
{
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{
return false;
}
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
{
return false;
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{
return false;
}
if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
// Sometimes these are marked hidden
if (_fileSystem.IsRootPath(args.Path))
if (_fileSystem.IsRootPath(path))
{
return false;
}
@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
if (args.IsDirectory)
if (fileInfo.IsDirectory)
{
// Ignore any folders in our list
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
// Ignore trailer folders but allow it at the collection level
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
!(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder))
if (parent != null)
{
return true;
}
// Ignore trailer folders but allow it at the collection level
if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
!(parent is AggregateFolder) && !(parent is UserRootFolder))
{
return true;
}
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{
return true;
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
else
{
if (args.Parent != null)
if (parent != null)
{
// Don't resolve these into audio files
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))

View file

@ -27,6 +27,7 @@ using MediaBrowser.Server.Implementations.Library.Validators;
using MediaBrowser.Server.Implementations.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
@ -36,6 +37,7 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
using MoreLinq;
using SortOrder = MediaBrowser.Model.Entities.SortOrder;
@ -140,6 +142,7 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly Func<ILibraryMonitor> _libraryMonitorFactory;
private readonly Func<IProviderManager> _providerManagerFactory;
private readonly Func<IUserViewManager> _userviewManager;
/// <summary>
/// The _library items cache
@ -167,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <param name="userManager">The user manager.</param>
/// <param name="configurationManager">The configuration manager.</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;
_taskManager = taskManager;
@ -177,6 +180,7 @@ namespace MediaBrowser.Server.Implementations.Library
_libraryMonitorFactory = libraryMonitorFactory;
_fileSystem = fileSystem;
_providerManagerFactory = providerManagerFactory;
_userviewManager = userviewManager;
ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>();
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
@ -401,12 +405,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
foreach (var path in item.GetDeletePaths().ToList())
{
if (_fileSystem.DirectoryExists(path))
if (_fileSystem.DirectoryExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteDirectory(path, true);
}
else if (_fileSystem.FileExists(path))
else if (_fileSystem.FileExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteFile(path);
@ -580,7 +584,7 @@ namespace MediaBrowser.Server.Implementations.Library
};
// Return null if ignore rules deem that we should do so
if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args)))
if (IgnoreFile(args.FileInfo, args.Parent))
{
return null;
}
@ -616,6 +620,11 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolveItem(args);
}
public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
{
return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
}
public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
{
var originalList = paths.ToList();
@ -651,7 +660,7 @@ namespace MediaBrowser.Server.Implementations.Library
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)
{
@ -702,7 +711,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
_fileSystem.CreateDirectory(rootFolderPath);
_fileSystem.CreateDirectory(rootFolderPath);
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath));
@ -732,6 +741,13 @@ namespace MediaBrowser.Server.Implementations.Library
folder = dbItem;
}
if (folder.ParentId != rootFolder.Id)
{
folder.ParentId = rootFolder.Id;
var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
Task.WaitAll(task);
}
rootFolder.AddVirtualChild(folder);
RegisterItem(folder);
@ -753,7 +769,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
_fileSystem.CreateDirectory(userRootPath);
_fileSystem.CreateDirectory(userRootPath);
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
@ -1005,9 +1021,9 @@ namespace MediaBrowser.Server.Implementations.Library
private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable<IHasMetadata> items)
{
}
/// <summary>
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
@ -1018,7 +1034,7 @@ namespace MediaBrowser.Server.Implementations.Library
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
{
// Ensure the location is available.
_fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
_fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
}
@ -1265,6 +1281,11 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
{
if (query.User != null)
{
AddUserToQuery(query, query.User);
}
var result = ItemRepository.GetItemIdsList(query);
var items = result.Select(GetItemById).Where(i => i != null).ToArray();
@ -1277,14 +1298,140 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult<BaseItem> QueryItems(InternalItemsQuery query)
{
if (query.User != null)
{
AddUserToQuery(query, query.User);
}
return ItemRepository.GetItems(query);
}
public List<Guid> GetItemIds(InternalItemsQuery query)
{
if (query.User != null)
{
AddUserToQuery(query, query.User);
}
return ItemRepository.GetItemIdsList(query);
}
public IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds)
{
var parents = parentIds.Select(i => GetItemById(new Guid(i))).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))).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>
/// Gets the intros.
/// </summary>
@ -1577,9 +1724,9 @@ namespace MediaBrowser.Server.Implementations.Library
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)
@ -1616,7 +1763,7 @@ namespace MediaBrowser.Server.Implementations.Library
return type;
}
return item.Parents
return item.GetParents()
.Select(GetConfiguredContentType)
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
@ -1653,16 +1800,16 @@ namespace MediaBrowser.Server.Implementations.Library
private string GetTopFolderContentType(BaseItem item)
{
while (!(item.Parent is AggregateFolder) && item.Parent != null)
{
item = item.Parent;
}
if (item == null)
{
return null;
}
while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
{
item = item.GetParent();
}
return GetUserRootFolder().Children
.OfType<ICollectionFolder>()
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path))
@ -1679,7 +1826,7 @@ namespace MediaBrowser.Server.Implementations.Library
string sortName,
CancellationToken cancellationToken)
{
return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
return GetNamedView(user, name, null, viewType, sortName, cancellationToken);
}
public async Task<UserView> GetNamedView(string name,
@ -1697,10 +1844,9 @@ namespace MediaBrowser.Server.Implementations.Library
var refresh = false;
if (item == null ||
!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
_fileSystem.CreateDirectory(path);
_fileSystem.CreateDirectory(path);
item = new UserView
{
@ -1717,12 +1863,6 @@ namespace MediaBrowser.Server.Implementations.Library
refresh = true;
}
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
{
item.ViewType = viewType;
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
if (!refresh)
{
refresh = (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
@ -1748,40 +1888,14 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
public Task<UserView> GetNamedView(User user,
public async Task<UserView> GetNamedView(User user,
string name,
string parentId,
string viewType,
string sortName,
string uniqueId,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(parentId))
{
throw new ArgumentNullException("parentId");
}
return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken);
}
private async Task<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 idValues = "38_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty) + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@ -1793,7 +1907,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
_fileSystem.CreateDirectory(path);
_fileSystem.CreateDirectory(path);
item = new UserView
{
@ -1816,18 +1930,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
if (!item.UserId.HasValue)
{
item.UserId = user.Id;
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
{
item.ViewType = viewType;
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@ -1851,7 +1953,6 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task<UserView> GetShadowView(BaseItem parent,
string viewType,
string sortName,
string uniqueId,
CancellationToken cancellationToken)
{
if (parent == null)
@ -1862,11 +1963,7 @@ namespace MediaBrowser.Server.Implementations.Library
var name = parent.Name;
var parentId = parent.Id;
var idValues = "37_namedview_" + name + parentId + (viewType ?? string.Empty);
if (!string.IsNullOrWhiteSpace(uniqueId))
{
idValues += uniqueId;
}
var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@ -1897,12 +1994,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
{
item.ViewType = viewType;
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@ -1922,7 +2013,7 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
public async Task<UserView> GetNamedView(string name,
string parentId,
string viewType,
@ -1951,7 +2042,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
_fileSystem.CreateDirectory(path);
_fileSystem.CreateDirectory(path);
item = new UserView
{
@ -2198,21 +2289,21 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolvePaths(files, directoryService, null, null)
.OfType<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
}).OrderBy(i => i.Path).ToList();
return video;
// 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)
@ -2384,7 +2475,7 @@ namespace MediaBrowser.Server.Implementations.Library
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)
{
_logger.Debug("ConvertImageToLocal item {0}", item.Id);
@ -2403,4 +2494,4 @@ namespace MediaBrowser.Server.Implementations.Library
return item.GetImageInfo(image.Type, imageIndex);
}
}
}
}

View file

@ -80,15 +80,13 @@ namespace MediaBrowser.Server.Implementations.Library
{
var genreList = genres.ToList();
var inputItems = _libraryManager.GetItems(new InternalItemsQuery
var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name },
Genres = genreList.ToArray(),
Genres = genreList.ToArray()
User = user
}).Items;
}, new string[] { });
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);

View file

@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library
item.Id = libraryManager.GetNewItemId(item.Path, item.GetType());
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
var fileInfo = directoryService.GetFile(item.Path);
@ -78,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.Library
EnsureName(item, args.FileInfo);
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
EnsureDates(fileSystem, item, args, true);

View file

@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
string collectionType,
IDirectoryService directoryService)
{
if (IsInvalid(parent, collectionType, files))
if (IsInvalid(parent, collectionType))
{
return null;
}
@ -95,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
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;
}
@ -185,7 +185,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
var collectionType = args.GetCollectionType();
if (IsInvalid(args.Parent, collectionType, args.FileSystemChildren))
if (IsInvalid(args.Parent, collectionType))
{
return null;
}
@ -193,14 +193,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
// Find movies with their own folders
if (args.IsDirectory)
{
var files = args.FileSystemChildren
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
.ToList();
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))
{
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))
@ -208,7 +212,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
// Owned items should just use the plain video type
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>())
@ -216,12 +220,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
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))
{
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;
@ -494,7 +498,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)
{

View file

@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
// Not officially supported but in some cases we can handle it.
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

View file

@ -156,19 +156,18 @@ namespace MediaBrowser.Server.Implementations.Library
}
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
var mediaItems = _libraryManager.GetItems(new InternalItemsQuery
var mediaItems = _libraryManager.GetItems(new InternalItemsQuery(user)
{
NameContains = searchTerm,
ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(),
MaxParentalRating = user == null ? null : user.Policy.MaxParentalRating,
Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 3) : null),
Limit = query.Limit,
}).Items;
}, new string[] { });
// 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);
@ -184,25 +183,6 @@ namespace MediaBrowser.Server.Implementations.Library
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)
{
var episode = item as Episode;

View file

@ -707,8 +707,7 @@ namespace MediaBrowser.Server.Implementations.Library
Id = Guid.NewGuid(),
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow,
UsesIdForConfigurationPath = true,
EnableUserViews = true
UsesIdForConfigurationPath = true
};
}

View file

@ -16,6 +16,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Server.Implementations.Library
{
@ -48,103 +49,63 @@ namespace MediaBrowser.Server.Implementations.Library
.OfType<Folder>()
.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 standaloneFolders = folders
.Where(i => UserView.IsExcludedFromGrouping(i) || !user.IsFolderGrouped(i.Id))
.ToList();
var foldersWithViewTypes = folders
.Except(standaloneFolders)
.OfType<ICollectionFolder>()
.ToList();
var groupedFolders = new List<ICollectionFolder>();
var list = new List<Folder>();
var enableUserViews = _config.Configuration.EnableUserViews || user.EnableUserViews;
if (enableUserViews)
foreach (var folder in folders)
{
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))
{
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
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);
}
if (UserView.IsUserSpecific(folder))
{
list.Add(await _libraryManager.GetNamedView(user, folder.Name, folder.Id.ToString("N"), folderViewType, null, cancellationToken).ConfigureAwait(false));
continue;
}
}
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))
{
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
else if (plainFolderIds.Contains(folder.Id))
{
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
else if (!string.IsNullOrWhiteSpace(folderViewType))
{
list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
else
{
list.Add(folder);
}
if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType))
{
list.Add(folder);
continue;
}
if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
{
groupedFolders.Add(collectionFolder);
continue;
}
if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
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)))
.ToList();
if (parents.Count > 0)
foreach (var viewType in new[] { CollectionType.Movies, CollectionType.TvShows })
{
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)))
.ToList();
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 (parents.Count > 0)
{
list.Add(await GetUserView(parents, viewType, string.Empty, user, query.PresetViews, cancellationToken).ConfigureAwait(false));
}
}
if (user.Configuration.DisplayFoldersView)
@ -180,6 +141,18 @@ namespace MediaBrowser.Server.Implementations.Library
{
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;
})
.ThenBy(sorted.IndexOf)
@ -200,32 +173,25 @@ namespace MediaBrowser.Server.Implementations.Library
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, enableRichView, string.Empty, cancellationToken).ConfigureAwait(false);
return await GetUserView((Folder)parents[0], viewType, string.Empty, cancellationToken).ConfigureAwait(false);
}
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
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.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);
return _libraryManager.GetShadowView(parent, viewType, sortName, cancellationToken);
}
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
@ -236,16 +202,8 @@ namespace MediaBrowser.Server.Implementations.Library
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)
{
var val = request.IsPlayed.Value;
@ -255,29 +213,12 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
return i.LocationType != LocationType.Virtual && !i.IsFolder;
};
// 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();
return true;
});
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
var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
@ -309,59 +250,34 @@ namespace MediaBrowser.Server.Implementations.Library
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));
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 user
.RootFolder
.GetRecursiveChildren(user, filter)
.ToList();
parentIds = user.RootFolder.GetChildren(user, true)
.OfType<Folder>()
.Select(i => i.Id.ToString("N"))
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i))
.ToArray();
}
return libraryManager
.RootFolder
.GetRecursiveChildren(filter);
}
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[] { };
private IEnumerable<BaseItem> GetItemsConfiguredForLatest(User user, Func<BaseItem, bool> filter)
{
// Avoid implicitly captured closure
var currentUser = user;
return _libraryManager.GetItems(new InternalItemsQuery(user)
{
IncludeItemTypes = includeItemTypes,
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)
.OfType<Folder>()
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N")))
.SelectMany(i => i.GetRecursiveChildren(currentUser, filter))
.DistinctBy(i => i.Id);
}, parentIds);
}
}
}

View file

@ -560,6 +560,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
item.ExternalId = channelInfo.Id;
if (!item.ParentId.Equals(parentFolderId))
{
isNew = true;
}
item.ParentId = parentFolderId;
item.ChannelType = channelInfo.ChannelType;
item.ServiceName = serviceName;
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;
if (!string.Equals(item.ServiceName, serviceName, StringComparison.Ordinal))
{
@ -774,6 +786,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
recording.IsSeries = info.IsSeries;
if (!item.ParentId.Equals(parentFolderId))
{
dataChanged = true;
}
item.ParentId = parentFolderId;
if (!item.HasImage(ImageType.Primary))
{
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 internalQuery = new InternalItemsQuery
var internalQuery = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
MinEndDate = query.MinEndDate,
@ -869,16 +887,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
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.Value)
@ -913,7 +921,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
var user = _userManager.GetUserById(query.UserId);
var internalQuery = new InternalItemsQuery
var internalQuery = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
IsAiring = query.IsAiring,
@ -922,16 +930,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
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.Value)
@ -1399,7 +1397,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await RefreshRecordings(cancellationToken).ConfigureAwait(false);
var internalQuery = new InternalItemsQuery
var internalQuery = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }
};
@ -1409,8 +1407,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
internalQuery.ChannelIds = new[] { query.ChannelId };
}
var queryResult = _libraryManager.GetItems(internalQuery);
IEnumerable<ILiveTvRecording> recordings = queryResult.Items.Cast<ILiveTvRecording>();
var queryResult = _libraryManager.GetItems(internalQuery, new string[] { });
IEnumerable<ILiveTvRecording> recordings = queryResult.Cast<ILiveTvRecording>();
if (!string.IsNullOrEmpty(query.Id))
{
@ -1516,6 +1514,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (channel != null)
{
dto.ChannelName = channel.Name;
dto.MediaType = channel.MediaType;
if (channel.HasImage(ImageType.Primary))
{
@ -1812,7 +1811,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var now = DateTime.UtcNow;
var programs = _libraryManager.GetItems(new InternalItemsQuery
var programs = _libraryManager.GetItems(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
ChannelIds = new[] { id },
@ -1821,7 +1820,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
Limit = 1,
SortBy = new[] { "StartDate" }
}).Items.Cast<LiveTvProgram>();
}, new string[] { }).Cast<LiveTvProgram>();
var currentProgram = programs.FirstOrDefault();
@ -1836,7 +1835,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var now = DateTime.UtcNow;
var programs = _libraryManager.GetItems(new InternalItemsQuery
var programs = _libraryManager.GetItems(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
ChannelIds = new[] { channel.Id.ToString("N") },
@ -1845,7 +1844,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
Limit = 1,
SortBy = new[] { "StartDate" }
}).Items.Cast<LiveTvProgram>();
}, new string[] { }).Cast<LiveTvProgram>();
var currentProgram = programs.FirstOrDefault();

View file

@ -154,7 +154,7 @@
"HeaderDisc": "Disc",
"HeaderTrack": "Track",
"HeaderAudio": "\u00c0udio",
"HeaderVideo": "Video",
"HeaderVideo": "V\u00eddeo",
"HeaderEmbeddedImage": "Embedded image",
"HeaderResolution": "Resolution",
"HeaderSubtitles": "Subtitles",

View file

@ -124,8 +124,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
if (extractImages)
{
if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso ||
video.VideoType == VideoType.BluRay)
if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay)
{
continue;
}

View file

@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Server.Implementations.Persistence
@ -24,6 +25,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
public const int MigrationVersion = 7;
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
@ -64,16 +67,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
innerProgress.RegisterAction(p => progress.Report(45 + (.55 * p)));
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
progress.Report(100);
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
}
private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress<double> progress)
{
var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IsCurrentSchema = false,
// These are constantly getting regenerated so don't bother with them here
ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name }
IsCurrentSchema = false
});
var numComplete = 0;
@ -115,9 +117,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
progress.Report(percent * 100);
}
if (!_config.Configuration.DisableStartupScan)
if (_config.Configuration.MigrationVersion < MigrationVersion)
{
_config.Configuration.DisableStartupScan = true;
_config.Configuration.MigrationVersion = MigrationVersion;
_config.SaveConfiguration();
}
@ -165,12 +167,22 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
{
IsOffline = false,
LocationType = LocationType.FileSystem,
//Limit = limit,
// These have their own cleanup routines
ExcludeItemTypes = new[] { typeof(Person).Name, typeof(Genre).Name, typeof(MusicGenre).Name, typeof(GameGenre).Name, typeof(Studio).Name, typeof(Year).Name }
ExcludeItemTypes = new[]
{
typeof(Person).Name,
typeof(Genre).Name,
typeof(MusicGenre).Name,
typeof(GameGenre).Name,
typeof(Studio).Name,
typeof(Year).Name,
typeof(Channel).Name,
typeof(AggregateFolder).Name,
typeof(CollectionFolder).Name
}
});
var numComplete = 0;
@ -191,6 +203,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
var libraryItem = _libraryManager.GetItemById(item.Item1);
if (libraryItem.IsTopParent)
{
continue;
}
if (Folder.IsPathOffline(path))
{
libraryItem.IsOffline = true;
@ -229,4 +246,4 @@ namespace MediaBrowser.Server.Implementations.Persistence
};
}
}
}
}

View file

@ -27,6 +27,70 @@ namespace MediaBrowser.Server.Implementations.Persistence
AddIsCabacColumn();
AddKeyFramesColumn();
AddRefFramesCommand();
AddCodecTagColumn();
AddCommentColumn();
}
private void AddCommentColumn()
{
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "PRAGMA table_info(mediastreams)";
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
if (!reader.IsDBNull(1))
{
var name = reader.GetString(1);
if (string.Equals(name, "Comment", StringComparison.OrdinalIgnoreCase))
{
return;
}
}
}
}
}
var builder = new StringBuilder();
builder.AppendLine("alter table mediastreams");
builder.AppendLine("add column Comment TEXT");
_connection.RunQueries(new[] { builder.ToString() }, _logger);
}
private void AddCodecTagColumn()
{
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "PRAGMA table_info(mediastreams)";
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
if (!reader.IsDBNull(1))
{
var name = reader.GetString(1);
if (string.Equals(name, "CodecTag", StringComparison.OrdinalIgnoreCase))
{
return;
}
}
}
}
}
var builder = new StringBuilder();
builder.AppendLine("alter table mediastreams");
builder.AppendLine("add column CodecTag TEXT");
_connection.RunQueries(new[] { builder.ToString() }, _logger);
}
private void AddPixelFormatColumnCommand()

View file

@ -19,6 +19,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Server.Implementations.Persistence
{
@ -76,7 +77,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deleteStreamsCommand;
private IDbCommand _saveStreamCommand;
private const int LatestSchemaVersion = 13;
private IDbCommand _deleteAncestorsCommand;
private IDbCommand _saveAncestorCommand;
private IDbCommand _updateInheritedRatingCommand;
private const int LatestSchemaVersion = 40;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
@ -121,17 +127,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
var createMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, KeyFrames TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = {
"create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB)",
"create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID)",
"create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)",
"create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
"create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))",
"create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
"create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
"create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))",
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
"create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
"create index if not exists idxPeopleItemId on People(ItemId)",
"create index if not exists idxPeopleName on People(Name)",
"create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
"create index if not exists idx_"+ChaptersTableName+" on "+ChaptersTableName+"(ItemId, ChapterIndex)",
@ -147,6 +160,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.RunQueries(queries, _logger);
_connection.AddColumn(_logger, "AncestorIds", "AncestorIdText", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "Path", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "StartDate", "DATETIME");
_connection.AddColumn(_logger, "TypedBaseItems", "EndDate", "DATETIME");
@ -198,6 +213,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(_logger, "TypedBaseItems", "ExternalEtag", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME");
_connection.AddColumn(_logger, "TypedBaseItems", "DateLastSaved", "DATETIME");
_connection.AddColumn(_logger, "TypedBaseItems", "IsInMixedFolder", "BIT");
_connection.AddColumn(_logger, "TypedBaseItems", "LockedFields", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "Studios", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "IsFolder", "BIT");
_connection.AddColumn(_logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT");
_connection.AddColumn(_logger, "TypedBaseItems", "UnratedType", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "TopParentId", "Text");
PrepareStatements();
new MediaStreamColumns(_connection, _logger).AddColumns();
@ -307,7 +334,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
"DateLastRefreshed"
"DateLastRefreshed",
"Name",
"Path",
"PremiereDate",
"Overview",
"ParentIndexNumber",
"ProductionYear",
"OfficialRating",
"OfficialRatingDescription",
"HomePageUrl",
"DisplayMediaType",
"ForcedSortName",
"RunTimeTicks",
"VoteCount",
"DateCreated",
"DateModified",
"guid",
"Genres",
"ParentId",
"Audio",
"ExternalServiceId"
};
private readonly string[] _mediaStreamSaveColumns =
@ -338,7 +385,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"IsAnamorphic",
"RefFrames",
"IsCabac",
"KeyFrames"
"CodecTag",
"Comment"
};
/// <summary>
@ -378,6 +426,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
"ParentId",
"Genres",
"ParentalRatingValue",
"InheritedParentalRatingValue",
"SchemaVersion",
"SortName",
"RunTimeTicks",
@ -394,7 +443,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
"DateLastRefreshed"
"DateLastRefreshed",
"DateLastSaved",
"IsInMixedFolder",
"LockedFields",
"Studios",
"Audio",
"ExternalServiceId",
"Tags",
"IsFolder",
"UnratedType",
"TopParentId"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@ -438,6 +497,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
_savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder");
_savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder");
// Ancestors
_deleteAncestorsCommand = _connection.CreateCommand();
_deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id";
_deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id");
_saveAncestorCommand = _connection.CreateCommand();
_saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)";
_saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId");
_saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId");
_saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText");
// Chapters
_deleteChaptersCommand = _connection.CreateCommand();
_deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId";
@ -467,6 +537,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
_saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col);
}
_updateInheritedRatingCommand = _connection.CreateCommand();
_updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid";
_updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue");
_updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid");
}
/// <summary>
@ -592,7 +667,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray());
_saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue();
_saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0;
_saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0;
_saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion;
_saveItemCommand.GetParameter(index++).Value = item.SortName;
@ -623,9 +699,53 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed;
}
_saveItemCommand.GetParameter(index++).Value = item.DateLastSaved;
_saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder;
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray());
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray());
if (item.Audio.HasValue)
{
_saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString();
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
var tvItem = item as ILiveTvItem;
if (tvItem != null)
{
_saveItemCommand.GetParameter(index++).Value = tvItem.ServiceName;
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray());
_saveItemCommand.GetParameter(index++).Value = item.IsFolder;
_saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString();
var topParent = item.GetTopParent();
if (topParent != null)
{
_saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N");
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
_saveItemCommand.Transaction = transaction;
_saveItemCommand.ExecuteNonQuery();
if (item.SupportsAncestors)
{
UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction);
}
}
transaction.Commit();
@ -706,22 +826,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
return null;
}
BaseItem item;
BaseItem item = null;
using (var stream = reader.GetMemoryStream(1))
{
try
{
item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
if (item == null)
{
return null;
}
}
catch (SerializationException ex)
{
_logger.ErrorException("Error deserializing item", ex);
}
if (item == null)
{
try
{
item = Activator.CreateInstance(type) as BaseItem;
}
catch
{
}
}
if (item == null)
{
return null;
}
}
@ -844,6 +974,107 @@ namespace MediaBrowser.Server.Implementations.Persistence
item.DateLastRefreshed = reader.GetDateTime(23).ToUniversalTime();
}
if (!reader.IsDBNull(24))
{
item.Name = reader.GetString(24);
}
if (!reader.IsDBNull(25))
{
item.Path = reader.GetString(25);
}
if (!reader.IsDBNull(26))
{
item.PremiereDate = reader.GetDateTime(26).ToUniversalTime();
}
if (!reader.IsDBNull(27))
{
item.Overview = reader.GetString(27);
}
if (!reader.IsDBNull(28))
{
item.ParentIndexNumber = reader.GetInt32(28);
}
if (!reader.IsDBNull(29))
{
item.ProductionYear = reader.GetInt32(29);
}
if (!reader.IsDBNull(30))
{
item.OfficialRating = reader.GetString(30);
}
if (!reader.IsDBNull(31))
{
item.OfficialRating = reader.GetString(31);
}
if (!reader.IsDBNull(32))
{
item.HomePageUrl = reader.GetString(32);
}
if (!reader.IsDBNull(33))
{
item.DisplayMediaType = reader.GetString(33);
}
if (!reader.IsDBNull(34))
{
item.ForcedSortName = reader.GetString(34);
}
if (!reader.IsDBNull(35))
{
item.RunTimeTicks = reader.GetInt64(35);
}
if (!reader.IsDBNull(36))
{
item.VoteCount = reader.GetInt32(36);
}
if (!reader.IsDBNull(37))
{
item.DateCreated = reader.GetDateTime(37).ToUniversalTime();
}
if (!reader.IsDBNull(38))
{
item.DateModified = reader.GetDateTime(38).ToUniversalTime();
}
item.Id = reader.GetGuid(39);
if (!reader.IsDBNull(40))
{
item.Genres = reader.GetString(40).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
}
if (!reader.IsDBNull(41))
{
item.ParentId = reader.GetGuid(41);
}
if (!reader.IsDBNull(42))
{
item.Audio = (ProgramAudio)Enum.Parse(typeof(ProgramAudio), reader.GetString(42), true);
}
if (!reader.IsDBNull(43))
{
var tvItem = item as ILiveTvItem;
if (tvItem != null)
{
tvItem.ServiceName = reader.GetString(43);
}
}
return item;
}
@ -1168,6 +1399,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
//_logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
@ -1213,6 +1446,50 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
CheckDisposed();
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
var whereClauses = GetWhereClauses(query, cmd, true);
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
cmd.CommandText += whereText;
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
//_logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var item = GetItem(reader);
if (item != null)
{
yield return item;
}
}
}
}
}
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
{
if (query == null)
@ -1293,6 +1570,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private string MapOrderByField(string name)
{
if (string.Equals(name, "airtime", StringComparison.OrdinalIgnoreCase))
{
// TODO
return "SortName";
}
return name;
}
@ -1328,7 +1611,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
@ -1512,6 +1795,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("IsSports=@IsSports");
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
}
if (query.IsFolder.HasValue)
{
whereClauses.Add("IsFolder=@IsFolder");
cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder;
}
var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray();
if (includeTypes.Length == 1)
@ -1572,6 +1860,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value;
}
if (query.MinPremiereDate.HasValue)
{
whereClauses.Add("PremiereDate>=@MinPremiereDate");
cmd.Parameters.Add(cmd, "@MinPremiereDate", DbType.Date).Value = query.MinPremiereDate.Value;
}
if (query.MaxStartDate.HasValue)
{
whereClauses.Add("StartDate<=@MaxStartDate");
@ -1623,7 +1917,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (query.MaxParentalRating.HasValue)
{
whereClauses.Add("(ParentalRatingValue is NULL OR ParentalRatingValue<=@MaxParentalRating)");
whereClauses.Add("InheritedParentalRatingValue<=@MaxParentalRating");
cmd.Parameters.Add(cmd, "@MaxParentalRating", DbType.Int32).Value = query.MaxParentalRating.Value;
}
@ -1631,11 +1925,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (query.HasParentalRating.Value)
{
whereClauses.Add("ParentalRatingValue NOT NULL");
whereClauses.Add("InheritedParentalRatingValue > 0");
}
else
{
whereClauses.Add("ParentalRatingValue IS NULL");
whereClauses.Add("InheritedParentalRatingValue = 0");
}
}
@ -1646,7 +1940,60 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("ParentId NOT NULL AND ParentId NOT IN (select guid from TypedBaseItems)");
}
}
if (query.ExcludeLocationTypes.Length == 1)
{
whereClauses.Add("LocationType<>@LocationType");
cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.ExcludeLocationTypes[0].ToString();
}
if (query.ExcludeLocationTypes.Length > 1)
{
var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray());
whereClauses.Add("LocationType not in (" + val + ")");
}
if (query.TopParentIds.Length == 1)
{
whereClauses.Add("(TopParentId=@TopParentId)");
cmd.Parameters.Add(cmd, "@TopParentId", DbType.String).Value = query.TopParentIds[0];
}
if (query.TopParentIds.Length > 1)
{
var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray());
whereClauses.Add("(TopParentId in (" + val + "))");
}
if (query.AncestorIds.Length == 1)
{
whereClauses.Add("Guid in (select itemId from AncestorIds where AncestorId=@AncestorId)");
cmd.Parameters.Add(cmd, "@AncestorId", DbType.Guid).Value = new Guid(query.AncestorIds[0]);
}
if (query.AncestorIds.Length > 1)
{
var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + new Guid(i).ToString("N") + "'").ToArray());
whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause));
}
if (query.BlockUnratedItems.Length == 1)
{
whereClauses.Add("(InheritedParentalRatingValue > 0 or UnratedType <> @UnratedType)");
cmd.Parameters.Add(cmd, "@UnratedType", DbType.String).Value = query.BlockUnratedItems[0].ToString();
}
if (query.BlockUnratedItems.Length > 1)
{
var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'").ToArray());
whereClauses.Add(string.Format("(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", inClause));
}
//var excludeTagIndex = 0;
//foreach (var excludeTag in query.ExcludeTags)
//{
// whereClauses.Add("Tags not like @excludeTag" + excludeTagIndex);
// cmd.Parameters.Add(cmd, "@excludeTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%";
// excludeTagIndex++;
//}
if (addPaging)
{
if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
@ -1703,6 +2050,83 @@ namespace MediaBrowser.Server.Implementations.Persistence
typeof(AggregateFolder)
};
public async Task UpdateInheritedValues(CancellationToken cancellationToken)
{
var newValues = new List<Tuple<Guid, int>>();
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue";
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var id = reader.GetGuid(0);
var newValue = reader.GetInt32(2);
newValues.Add(new Tuple<Guid, int>(id, newValue));
}
}
}
if (newValues.Count == 0)
{
return;
}
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
foreach (var item in newValues)
{
_updateInheritedRatingCommand.GetParameter(0).Value = item.Item1;
_updateInheritedRatingCommand.GetParameter(1).Value = item.Item2;
_updateInheritedRatingCommand.Transaction = transaction;
_updateInheritedRatingCommand.ExecuteNonQuery();
_updateInheritedRatingCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
_logger.ErrorException("Error running query:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
_writeLock.Release();
}
}
private static Dictionary<string, string[]> GetTypeMapDictionary()
{
var dict = new Dictionary<string, string[]>();
@ -1712,6 +2136,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
dict[t.Name] = new[] { t.FullName };
}
dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName };
dict["LiveTvItem"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName, typeof(LiveTvChannel).FullName, typeof(LiveTvProgram).FullName };
dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName };
dict["Program"] = new[] { typeof(LiveTvProgram).FullName };
dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName };
@ -1770,11 +2196,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteStreamsCommand.Transaction = transaction;
_deleteStreamsCommand.ExecuteNonQuery();
// Delete ancestors
_deleteAncestorsCommand.GetParameter(0).Value = id;
_deleteAncestorsCommand.Transaction = transaction;
_deleteAncestorsCommand.ExecuteNonQuery();
// Delete the item
_deleteItemCommand.GetParameter(0).Value = id;
_deleteItemCommand.Transaction = transaction;
_deleteItemCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
@ -2003,6 +2434,38 @@ namespace MediaBrowser.Server.Implementations.Persistence
return whereClauses;
}
private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, IDbTransaction transaction)
{
if (itemId == Guid.Empty)
{
throw new ArgumentNullException("itemId");
}
if (ancestorIds == null)
{
throw new ArgumentNullException("ancestorIds");
}
CheckDisposed();
// First delete
_deleteAncestorsCommand.GetParameter(0).Value = itemId;
_deleteAncestorsCommand.Transaction = transaction;
_deleteAncestorsCommand.ExecuteNonQuery();
foreach (var ancestorId in ancestorIds)
{
_saveAncestorCommand.GetParameter(0).Value = itemId;
_saveAncestorCommand.GetParameter(1).Value = ancestorId;
_saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N");
_saveAncestorCommand.Transaction = transaction;
_saveAncestorCommand.ExecuteNonQuery();
}
}
public async Task UpdatePeople(Guid itemId, List<PersonInfo> people)
{
if (itemId == Guid.Empty)
@ -2220,7 +2683,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveStreamCommand.GetParameter(index++).Value = stream.RefFrames;
_saveStreamCommand.GetParameter(index++).Value = stream.IsCabac;
_saveStreamCommand.GetParameter(index++).Value = null;
_saveStreamCommand.GetParameter(index++).Value = stream.CodecTag;
_saveStreamCommand.GetParameter(index++).Value = stream.Comment;
_saveStreamCommand.Transaction = transaction;
_saveStreamCommand.ExecuteNonQuery();
@ -2376,10 +2840,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!reader.IsDBNull(26))
{
var frames = reader.GetString(26);
if (!string.IsNullOrWhiteSpace(frames))
{
}
item.CodecTag = reader.GetString(26);
}
if (!reader.IsDBNull(27))
{
item.Comment = reader.GetString(27);
}
return item;

Some files were not shown because too many files have changed in this diff Show more