mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-16 10:29:01 -07:00
Merge branch 'beta'
This commit is contained in:
commit
b253d26aba
@ -103,7 +103,8 @@ namespace MediaBrowser.Api
|
||||
User = user,
|
||||
MediaTypes = request.GetMediaTypes(),
|
||||
IncludeItemTypes = request.GetIncludeItemTypes(),
|
||||
Recursive = true
|
||||
Recursive = true,
|
||||
EnableTotalRecordCount = false
|
||||
};
|
||||
|
||||
return query;
|
||||
|
@ -162,7 +162,10 @@ namespace MediaBrowser.Api
|
||||
|
||||
var items = user == null ?
|
||||
system.GetRecursiveChildren(i => i is Game) :
|
||||
system.GetRecursiveChildren(user, i => i is Game);
|
||||
system.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Game).Name }
|
||||
});
|
||||
|
||||
var games = items.Cast<Game>().ToList();
|
||||
|
||||
|
@ -65,11 +65,7 @@ namespace MediaBrowser.Api
|
||||
public void Post(ReportStartupWizardComplete request)
|
||||
{
|
||||
_config.Configuration.IsStartupWizardCompleted = true;
|
||||
_config.Configuration.EnableLocalizedGuids = true;
|
||||
_config.Configuration.EnableCustomPathSubFolders = true;
|
||||
_config.Configuration.EnableDateLastRefresh = true;
|
||||
_config.Configuration.EnableStandaloneMusicKeys = true;
|
||||
_config.Configuration.EnableCaseSensitiveItemIds = true;
|
||||
SetWizardFinishValues(_config.Configuration);
|
||||
_config.SaveConfiguration();
|
||||
}
|
||||
|
||||
@ -111,6 +107,15 @@ namespace MediaBrowser.Api
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SetWizardFinishValues(ServerConfiguration config)
|
||||
{
|
||||
config.EnableLocalizedGuids = true;
|
||||
config.EnableCustomPathSubFolders = true;
|
||||
config.EnableDateLastRefresh = true;
|
||||
config.EnableStandaloneMusicKeys = true;
|
||||
config.EnableCaseSensitiveItemIds = true;
|
||||
}
|
||||
|
||||
public void Post(UpdateStartupConfiguration request)
|
||||
{
|
||||
_config.Configuration.UICulture = request.UICulture;
|
||||
|
@ -415,21 +415,10 @@ namespace MediaBrowser.Api
|
||||
|
||||
private IEnumerable<Season> FilterVirtualSeasons(GetSeasons request, IEnumerable<Season> items)
|
||||
{
|
||||
if (request.IsMissing.HasValue && request.IsVirtualUnaired.HasValue)
|
||||
{
|
||||
var isMissing = request.IsMissing.Value;
|
||||
var isVirtualUnaired = request.IsVirtualUnaired.Value;
|
||||
|
||||
if (!isMissing && !isVirtualUnaired)
|
||||
{
|
||||
return items.Where(i => !i.IsMissingOrVirtualUnaired);
|
||||
}
|
||||
}
|
||||
|
||||
if (request.IsMissing.HasValue)
|
||||
{
|
||||
var val = request.IsMissing.Value;
|
||||
items = items.Where(i => (i.IsMissingSeason ?? false) == val);
|
||||
items = items.Where(i => (i.IsMissingSeason) == val);
|
||||
}
|
||||
|
||||
if (request.IsVirtualUnaired.HasValue)
|
||||
|
@ -121,6 +121,13 @@ namespace MediaBrowser.Api.UserLibrary
|
||||
var includeItemTypes = request.GetIncludeItemTypes();
|
||||
var mediaTypes = request.GetMediaTypes();
|
||||
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
ExcludeItemTypes = excludeItemTypes,
|
||||
IncludeItemTypes = includeItemTypes,
|
||||
MediaTypes = mediaTypes
|
||||
};
|
||||
|
||||
Func<BaseItem, bool> filter = i => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes);
|
||||
|
||||
if (parentItem.IsFolder)
|
||||
@ -130,7 +137,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||
if (!string.IsNullOrWhiteSpace(request.UserId))
|
||||
{
|
||||
items = request.Recursive ?
|
||||
folder.GetRecursiveChildren(user, filter) :
|
||||
folder.GetRecursiveChildren(user, query) :
|
||||
folder.GetChildren(user, true).Where(filter);
|
||||
}
|
||||
else
|
||||
|
@ -138,25 +138,19 @@ namespace MediaBrowser.Api.UserLibrary
|
||||
|
||||
if (request.Recursive)
|
||||
{
|
||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
return await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var userRoot = item as UserRootFolder;
|
||||
|
||||
if (userRoot == null)
|
||||
{
|
||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);
|
||||
|
@ -55,7 +55,7 @@
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.3.1\lib\net45\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.3.4\lib\net45\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Patterns.Logging">
|
||||
@ -65,8 +65,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=3.1.3.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
|
@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="NLog" version="4.3.1" targetFramework="net45" />
|
||||
<package id="NLog" version="4.3.4" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.1.3" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.1.4" targetFramework="net45" />
|
||||
</packages>
|
@ -64,10 +64,37 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return CreateResolveArgs(directoryService).FileSystemChildren;
|
||||
return CreateResolveArgs(directoryService, true).FileSystemChildren;
|
||||
}
|
||||
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService)
|
||||
private bool _requiresRefresh;
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var changed = base.RequiresRefresh() || _requiresRefresh;
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
var locations = PhysicalLocations.ToList();
|
||||
|
||||
var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
|
||||
|
||||
if (!locations.SequenceEqual(newLocations))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh()
|
||||
{
|
||||
var changed = base.BeforeMetadataRefresh() || _requiresRefresh;
|
||||
_requiresRefresh = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
|
||||
{
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
@ -100,7 +127,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
args.FileSystemDictionary = fileSystemDictionary;
|
||||
}
|
||||
|
||||
PhysicalLocationsList = args.PhysicalLocations.ToList();
|
||||
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
|
||||
if (setPhysicalLocations)
|
||||
{
|
||||
PhysicalLocationsList = args.PhysicalLocations.ToList();
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
@ -56,38 +56,23 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
||||
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
var itemByNameFilter = GetItemFilter();
|
||||
|
||||
if (query.User != null)
|
||||
if (query.IncludeItemTypes.Length == 0)
|
||||
{
|
||||
return query.User.RootFolder
|
||||
.GetRecursiveChildren(query.User, i =>
|
||||
{
|
||||
if (query.IsFolder.HasValue)
|
||||
{
|
||||
if (query.IsFolder.Value != i.IsFolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return itemByNameFilter(i);
|
||||
});
|
||||
query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
|
||||
query.ArtistNames = new[] { Name };
|
||||
}
|
||||
|
||||
return LibraryManager.RootFolder
|
||||
.GetRecursiveChildren(i =>
|
||||
{
|
||||
if (query.IsFolder.HasValue)
|
||||
{
|
||||
if (query.IsFolder.Value != i.IsFolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return itemByNameFilter(i);
|
||||
});
|
||||
// Need this for now since the artist filter isn't yet supported by the db
|
||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
||||
{
|
||||
var filter = GetItemFilter();
|
||||
return LibraryManager.GetItemList(query).Where(filter);
|
||||
}
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
protected override IEnumerable<BaseItem> ActualChildren
|
||||
{
|
||||
get
|
||||
|
@ -23,19 +23,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
PhysicalLocationsList = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is virtual folder.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is virtual folder; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public override bool IsVirtualFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
protected override bool SupportsShortcutChildren
|
||||
{
|
||||
@ -83,7 +70,34 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return CreateResolveArgs(directoryService).FileSystemChildren;
|
||||
return CreateResolveArgs(directoryService, true).FileSystemChildren;
|
||||
}
|
||||
|
||||
private bool _requiresRefresh;
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var changed = base.RequiresRefresh() || _requiresRefresh;
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
var locations = PhysicalLocations.ToList();
|
||||
|
||||
var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
|
||||
|
||||
if (!locations.SequenceEqual(newLocations))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh()
|
||||
{
|
||||
var changed = base.BeforeMetadataRefresh() || _requiresRefresh;
|
||||
_requiresRefresh = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
internal override bool IsValidFromResolver(BaseItem newItem)
|
||||
@ -101,7 +115,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return base.IsValidFromResolver(newItem);
|
||||
}
|
||||
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService)
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
|
||||
{
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
@ -135,7 +149,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
args.FileSystemDictionary = fileSystemDictionary;
|
||||
}
|
||||
|
||||
PhysicalLocationsList = args.PhysicalLocations.ToList();
|
||||
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
|
||||
if (setPhysicalLocations)
|
||||
{
|
||||
PhysicalLocationsList = args.PhysicalLocations.ToList();
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
@ -153,15 +171,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
|
||||
{
|
||||
var list = PhysicalLocationsList.ToList();
|
||||
|
||||
CreateResolveArgs(directoryService);
|
||||
|
||||
if (!list.SequenceEqual(PhysicalLocationsList))
|
||||
{
|
||||
return UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken);
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
@ -188,6 +197,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Our children are actually just references to the ones in the physical root...
|
||||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
[IgnoreDataMember]
|
||||
protected override IEnumerable<BaseItem> ActualChildren
|
||||
{
|
||||
get { return GetActualChildren(); }
|
||||
|
@ -126,19 +126,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value>
|
||||
public bool IsRoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is virtual folder.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is virtual folder; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public virtual bool IsVirtualFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual List<LinkedChild> LinkedChildren { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
@ -285,6 +272,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Gets the actual children.
|
||||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
[IgnoreDataMember]
|
||||
protected virtual IEnumerable<BaseItem> ActualChildren
|
||||
{
|
||||
get
|
||||
@ -749,7 +737,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var user = query.User;
|
||||
|
||||
if (RequiresPostFiltering(query))
|
||||
if (!query.ForceDirect && RequiresPostFiltering(query))
|
||||
{
|
||||
IEnumerable<BaseItem> items;
|
||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||
@ -760,7 +748,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
items = GetRecursiveChildren(user, filter);
|
||||
items = GetRecursiveChildren(user, query);
|
||||
}
|
||||
|
||||
return PostFilterAndSort(items, query);
|
||||
@ -784,7 +772,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
|
||||
|
||||
if (query.SortBy != null && query.SortBy.Length > 0)
|
||||
@ -817,21 +805,26 @@ namespace MediaBrowser.Controller.Entities
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
||||
{
|
||||
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
||||
return true;
|
||||
}
|
||||
if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
||||
return true;
|
||||
}
|
||||
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
||||
return true;
|
||||
}
|
||||
if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
|
||||
return true;
|
||||
}
|
||||
if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
||||
@ -1109,10 +1102,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
if (query.ArtistNames.Length > 0)
|
||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
||||
return true;
|
||||
if (query.ArtistNames.Length > 0)
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1178,7 +1174,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
else
|
||||
{
|
||||
items = query.Recursive
|
||||
? GetRecursiveChildren(user, filter)
|
||||
? GetRecursiveChildren(user, query)
|
||||
: GetChildren(user, true).Where(filter);
|
||||
}
|
||||
|
||||
@ -1215,19 +1211,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <summary>
|
||||
/// Adds the children to list.
|
||||
/// </summary>
|
||||
/// <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="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 recursive, Func<BaseItem, bool> filter)
|
||||
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query)
|
||||
{
|
||||
foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
|
||||
{
|
||||
if (child.IsVisible(user))
|
||||
{
|
||||
if (filter == null || filter(child))
|
||||
if (query == null || UserViewBuilder.FilterItem(child, query))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
@ -1236,7 +1227,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var folder = (Folder)child;
|
||||
|
||||
folder.AddChildren(user, includeLinkedChildren, result, true, filter);
|
||||
folder.AddChildren(user, includeLinkedChildren, result, true, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1247,7 +1238,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
if (child.IsVisible(user))
|
||||
{
|
||||
if (filter == null || filter(child))
|
||||
if (query == null || UserViewBuilder.FilterItem(child, query))
|
||||
{
|
||||
result[child.Id] = child;
|
||||
}
|
||||
@ -1265,10 +1256,10 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
|
||||
{
|
||||
return GetRecursiveChildren(user, i => true);
|
||||
return GetRecursiveChildren(user, null);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
||||
public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@ -1277,7 +1268,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var result = new Dictionary<Guid, BaseItem>();
|
||||
|
||||
AddChildren(user, true, result, true, filter);
|
||||
AddChildren(user, true, result, true, query);
|
||||
|
||||
return result.Values;
|
||||
}
|
||||
@ -1303,7 +1294,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <summary>
|
||||
/// Adds the children to list.
|
||||
/// </summary>
|
||||
private void AddChildrenToList(Dictionary<Guid,BaseItem> result, bool includeLinkedChildren, bool recursive, Func<BaseItem, bool> filter)
|
||||
private void AddChildrenToList(Dictionary<Guid, BaseItem> result, bool includeLinkedChildren, bool recursive, Func<BaseItem, bool> filter)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
@ -1534,13 +1525,12 @@ namespace MediaBrowser.Controller.Entities
|
||||
User = user,
|
||||
Recursive = true,
|
||||
IsFolder = false,
|
||||
IsUnaired = false
|
||||
|
||||
EnableTotalRecordCount = false
|
||||
};
|
||||
|
||||
if (!user.Configuration.DisplayMissingEpisodes)
|
||||
if (!user.Configuration.DisplayMissingEpisodes || !user.Configuration.DisplayUnairedEpisodes)
|
||||
{
|
||||
query.IsMissing = false;
|
||||
query.ExcludeLocationTypes = new[] { LocationType.Virtual };
|
||||
}
|
||||
|
||||
var itemsResult = await GetItems(query).ConfigureAwait(false);
|
||||
@ -1562,7 +1552,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
User = user,
|
||||
Recursive = true,
|
||||
IsFolder = false
|
||||
IsFolder = false,
|
||||
EnableTotalRecordCount = false
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
@ -1578,7 +1569,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
Recursive = true,
|
||||
IsFolder = false,
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
||||
EnableTotalRecordCount = false
|
||||
|
||||
}).Result;
|
||||
|
||||
@ -1630,7 +1622,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
Recursive = true,
|
||||
IsFolder = false,
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
||||
EnableTotalRecordCount = false
|
||||
|
||||
}).Result;
|
||||
|
||||
|
@ -15,12 +15,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item filter.
|
||||
/// </summary>
|
||||
/// <returns>Func<BaseItem, System.Boolean>.</returns>
|
||||
Func<BaseItem, bool> GetItemFilter();
|
||||
|
||||
IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public User User { get; set; }
|
||||
|
||||
public Func<BaseItem, bool> Filter { get; set; }
|
||||
|
||||
public bool? IsFolder { get; set; }
|
||||
public bool? IsFavorite { get; set; }
|
||||
public bool? IsFavoriteOrLiked { get; set; }
|
||||
@ -138,6 +136,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public bool GroupByPresentationUniqueKey { get; set; }
|
||||
public bool EnableTotalRecordCount { get; set; }
|
||||
public bool ForceDirect { get; set; }
|
||||
|
||||
public InternalItemsQuery()
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
if (!result)
|
||||
{
|
||||
if (!IsMissingSeason.HasValue)
|
||||
if (!IsVirtualItem.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -144,18 +144,23 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool? IsMissingSeason { get; set; }
|
||||
public bool? IsVirtualItem { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsMissingSeason
|
||||
{
|
||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsVirtualUnaired
|
||||
{
|
||||
get { return LocationType == LocationType.Virtual && IsUnaired; }
|
||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsMissingOrVirtualUnaired
|
||||
private bool DetectIsVirtualItem()
|
||||
{
|
||||
get { return (IsMissingSeason ?? false) || (LocationType == LocationType.Virtual && IsUnaired); }
|
||||
return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
@ -319,19 +324,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh();
|
||||
|
||||
var locationType = LocationType;
|
||||
|
||||
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
|
||||
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
|
||||
{
|
||||
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
|
||||
{
|
||||
IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path);
|
||||
IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path);
|
||||
|
||||
// If a change was made record it
|
||||
if (IndexNumber.HasValue)
|
||||
{
|
||||
hasChanges = true;
|
||||
}
|
||||
// If a change was made record it
|
||||
if (IndexNumber.HasValue)
|
||||
{
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,20 +238,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
||||
}
|
||||
|
||||
if (!includeMissingSeasons && !includeVirtualUnaired)
|
||||
if (!includeMissingSeasons)
|
||||
{
|
||||
seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired);
|
||||
seasons = seasons.Where(i => !(i.IsMissingSeason));
|
||||
}
|
||||
else
|
||||
if (!includeVirtualUnaired)
|
||||
{
|
||||
if (!includeMissingSeasons)
|
||||
{
|
||||
seasons = seasons.Where(i => !(i.IsMissingSeason ?? false));
|
||||
}
|
||||
if (!includeVirtualUnaired)
|
||||
{
|
||||
seasons = seasons.Where(i => !i.IsVirtualUnaired);
|
||||
}
|
||||
seasons = seasons.Where(i => !i.IsVirtualUnaired);
|
||||
}
|
||||
|
||||
return seasons;
|
||||
@ -381,14 +374,18 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
}
|
||||
else
|
||||
{
|
||||
episodes = GetRecursiveChildren(user, i => i is Episode)
|
||||
.Cast<Episode>();
|
||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
||||
}).Cast<Episode>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
episodes = GetRecursiveChildren(user, i => i is Episode)
|
||||
.Cast<Episode>();
|
||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
||||
}).Cast<Episode>();
|
||||
}
|
||||
|
||||
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
|
||||
|
@ -305,14 +305,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public bool IsFolderGrouped(Guid id)
|
||||
{
|
||||
var config = Configuration;
|
||||
|
||||
if (config.ExcludeFoldersFromGrouping != null)
|
||||
{
|
||||
return !config.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).Contains(id);
|
||||
}
|
||||
|
||||
return config.GroupedFolders.Select(i => new Guid(i)).Contains(id);
|
||||
return Configuration.GroupedFolders.Select(i => new Guid(i)).Contains(id);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -64,15 +64,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
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);
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh()
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh();
|
||||
|
@ -66,7 +66,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var result = GetItems(new InternalItemsQuery
|
||||
{
|
||||
User = user
|
||||
User = user,
|
||||
EnableTotalRecordCount = false
|
||||
|
||||
}).Result;
|
||||
|
||||
@ -83,17 +84,19 @@ namespace MediaBrowser.Controller.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
|
||||
{
|
||||
var result = GetItems(new InternalItemsQuery
|
||||
{
|
||||
User = user,
|
||||
Recursive = true,
|
||||
Filter = filter
|
||||
EnableTotalRecordCount = false,
|
||||
|
||||
ForceDirect = true
|
||||
|
||||
}).Result;
|
||||
|
||||
return result.Items;
|
||||
return result.Items.Where(i => UserViewBuilder.FilterItem(i, query));
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
|
||||
|
@ -128,7 +128,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
if (query.Recursive)
|
||||
{
|
||||
return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
|
||||
query.Recursive = true;
|
||||
query.ParentId = queryParent.Id;
|
||||
query.SetUser(user);
|
||||
|
||||
return _libraryManager.GetItemsResult(query);
|
||||
}
|
||||
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
|
||||
}
|
||||
@ -251,7 +255,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.Recursive)
|
||||
{
|
||||
query.Recursive = true;
|
||||
query.ParentId = parent.Id;
|
||||
query.SetUser(user);
|
||||
|
||||
if (query.IncludeItemTypes.Length == 0)
|
||||
@ -259,7 +262,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
query.IncludeItemTypes = new[] { typeof(MusicArtist).Name, typeof(MusicAlbum).Name, typeof(Audio.Audio).Name, typeof(MusicVideo).Name };
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemsResult(query);
|
||||
return parent.QueryRecursive(query);
|
||||
}
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
@ -329,9 +332,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||
.Where(i => !i.IsFolder)
|
||||
.OfType<IHasAlbumArtist>();
|
||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
ParentId = parent.Id,
|
||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
||||
|
||||
}).Cast<IHasAlbumArtist>();
|
||||
|
||||
var artists = _libraryManager.GetAlbumArtists(items);
|
||||
|
||||
@ -340,9 +347,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||
.Where(i => !i.IsFolder)
|
||||
.OfType<IHasArtist>();
|
||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
ParentId = parent.Id,
|
||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }
|
||||
|
||||
}).Cast<IHasArtist>();
|
||||
|
||||
var artists = _libraryManager.GetArtists(items);
|
||||
|
||||
@ -351,9 +362,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||
.Where(i => !i.IsFolder)
|
||||
.OfType<IHasAlbumArtist>();
|
||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
ParentId = parent.Id,
|
||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
||||
|
||||
}).Cast<IHasAlbumArtist>();
|
||||
|
||||
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
||||
|
||||
@ -448,7 +463,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.Recursive)
|
||||
{
|
||||
query.Recursive = true;
|
||||
query.ParentId = parent.Id;
|
||||
query.SetUser(user);
|
||||
|
||||
if (query.IncludeItemTypes.Length == 0)
|
||||
@ -456,7 +470,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
query.IncludeItemTypes = new[] { typeof(Movie).Name, typeof(BoxSet).Name };
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemsResult(query);
|
||||
return parent.QueryRecursive(query);
|
||||
}
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
@ -613,7 +627,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
if (query.Recursive)
|
||||
{
|
||||
query.Recursive = true;
|
||||
query.ParentId = parent.Id;
|
||||
query.SetUser(user);
|
||||
|
||||
if (query.IncludeItemTypes.Length == 0)
|
||||
@ -621,7 +634,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
query.IncludeItemTypes = new[] { typeof(Series).Name, typeof(Season).Name, typeof(Episode).Name };
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemsResult(query);
|
||||
return parent.QueryRecursive(query);
|
||||
}
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
@ -756,9 +769,9 @@ namespace MediaBrowser.Controller.Entities
|
||||
return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
|
||||
}
|
||||
|
||||
public bool FilterItem(BaseItem item, InternalItemsQuery query)
|
||||
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
||||
{
|
||||
return Filter(item, query.User, query, _userDataManager, _libraryManager);
|
||||
return Filter(item, query.User, query, BaseItem.UserDataManager, BaseItem.LibraryManager);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
||||
@ -1121,22 +1134,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
bool? isVirtualUnaired,
|
||||
bool? isUnaired)
|
||||
{
|
||||
if (isMissing.HasValue && isVirtualUnaired.HasValue)
|
||||
{
|
||||
if (!isMissing.Value && !isVirtualUnaired.Value)
|
||||
{
|
||||
return items.Where(i =>
|
||||
{
|
||||
var e = i as Season;
|
||||
if (e != null)
|
||||
{
|
||||
return !e.IsMissingOrVirtualUnaired;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isMissing.HasValue)
|
||||
{
|
||||
var val = isMissing.Value;
|
||||
@ -1145,7 +1142,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var e = i as Season;
|
||||
if (e != null)
|
||||
{
|
||||
return (e.IsMissingSeason ?? false) == val;
|
||||
return (e.IsMissingSeason) == val;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@ -1277,11 +1274,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
if (query.Filter != null && !query.Filter(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UserItemData userData = null;
|
||||
|
||||
if (query.IsLiked.HasValue)
|
||||
|
@ -63,13 +63,13 @@ namespace MediaBrowser.Controller.Playlists
|
||||
return GetPlayableItems(user).Result;
|
||||
}
|
||||
|
||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
|
||||
{
|
||||
var items = GetPlayableItems(user).Result;
|
||||
|
||||
if (filter != null)
|
||||
if (query != null)
|
||||
{
|
||||
items = items.Where(filter);
|
||||
items = items.Where(i => UserViewBuilder.FilterItem(i, query));
|
||||
}
|
||||
|
||||
return items;
|
||||
@ -129,7 +129,11 @@ namespace MediaBrowser.Controller.Playlists
|
||||
|
||||
var items = user == null
|
||||
? LibraryManager.RootFolder.GetRecursiveChildren(filter)
|
||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
||||
: user.RootFolder.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
||||
ArtistNames = new[] { musicArtist.Name }
|
||||
});
|
||||
|
||||
return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
|
||||
}
|
||||
|
@ -401,10 +401,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||
SortOrder = sort.SortOrder,
|
||||
User = user,
|
||||
Recursive = true,
|
||||
Filter = FilterUnsupportedContent,
|
||||
IsMissing = false,
|
||||
ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
|
||||
IsFolder = isFolder,
|
||||
MediaTypes = mediaTypes.ToArray()
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -461,8 +461,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||
SortBy = sortOrders.ToArray(),
|
||||
SortOrder = sort.SortOrder,
|
||||
User = user,
|
||||
Filter = FilterUnsupportedContent,
|
||||
PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music }
|
||||
IsMissing = false,
|
||||
PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music },
|
||||
ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
|
||||
IsPlaceHolder = false
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
@ -579,29 +581,6 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
||||
});
|
||||
}
|
||||
|
||||
private bool FilterUnsupportedContent(BaseItem i)
|
||||
{
|
||||
// Unplayable
|
||||
if (i.LocationType == LocationType.Virtual && !i.IsFolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unplayable
|
||||
var supportsPlaceHolder = i as ISupportsPlaceHolders;
|
||||
if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i is Game || i is Book)
|
||||
{
|
||||
//return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private ServerItem GetItemFromObjectId(string id, User user)
|
||||
{
|
||||
return DidlBuilder.IsIdRoot(id)
|
||||
|
@ -215,6 +215,9 @@ namespace MediaBrowser.Model.Configuration
|
||||
{
|
||||
Migrations = new string[] { };
|
||||
|
||||
EnableLocalizedGuids = true;
|
||||
EnableCustomPathSubFolders = true;
|
||||
|
||||
ImageSavingConvention = ImageSavingConvention.Compatible;
|
||||
PublicPort = 8096;
|
||||
PublicHttpsPort = 8920;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using System.Diagnostics;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
|
||||
namespace MediaBrowser.Model.Entities
|
||||
{
|
||||
@ -53,18 +53,22 @@ namespace MediaBrowser.Model.Entities
|
||||
|
||||
if (!string.IsNullOrEmpty(Language))
|
||||
{
|
||||
attributes.Add(Language);
|
||||
attributes.Add(StringHelper.FirstToUpper(Language));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Codec) && !StringHelper.EqualsIgnoreCase(Codec, "dca"))
|
||||
{
|
||||
attributes.Add(Codec);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Profile) && !StringHelper.EqualsIgnoreCase(Profile, "lc"))
|
||||
attributes.Add(AudioCodec.GetFriendlyName(Codec));
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Profile) && !StringHelper.EqualsIgnoreCase(Profile, "lc"))
|
||||
{
|
||||
attributes.Add(Profile);
|
||||
}
|
||||
|
||||
if (Channels.HasValue)
|
||||
if (!string.IsNullOrEmpty(ChannelLayout))
|
||||
{
|
||||
attributes.Add(ChannelLayout);
|
||||
}
|
||||
else if (Channels.HasValue)
|
||||
{
|
||||
attributes.Add(StringHelper.ToStringCultureInvariant(Channels.Value) + " ch");
|
||||
}
|
||||
|
@ -125,5 +125,10 @@ namespace MediaBrowser.Model.Extensions
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string FirstToUpper(this string str)
|
||||
{
|
||||
return string.IsNullOrEmpty(str) ? "" : str.Substring(0, 1).ToUpper() + str.Substring(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,15 @@ namespace MediaBrowser.Model.LiveTv
|
||||
public int PrePaddingSeconds { get; set; }
|
||||
public int PostPaddingSeconds { get; set; }
|
||||
|
||||
public string[] MediaLocationsCreated { get; set; }
|
||||
|
||||
public LiveTvOptions()
|
||||
{
|
||||
EnableMovieProviders = true;
|
||||
EnableRecordingSubfolders = true;
|
||||
TunerHosts = new List<TunerHostInfo>();
|
||||
ListingProviders = new List<ListingsProviderInfo>();
|
||||
MediaLocationsCreated = new string[] { };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,5 +5,22 @@
|
||||
public const string AAC = "aac";
|
||||
public const string MP3 = "mp3";
|
||||
public const string AC3 = "ac3";
|
||||
|
||||
public static string GetFriendlyName(string codec)
|
||||
{
|
||||
if (string.IsNullOrEmpty(codec)) return "";
|
||||
|
||||
switch (codec.ToLower())
|
||||
{
|
||||
case "ac3":
|
||||
return "Dolby Digital";
|
||||
case "eac3":
|
||||
return "Dolby Digital+";
|
||||
case "dca":
|
||||
return "DTS";
|
||||
default:
|
||||
return codec.ToUpper();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -288,6 +288,8 @@ namespace MediaBrowser.Model.Querying
|
||||
[Obsolete]
|
||||
public string Person { get; set; }
|
||||
|
||||
public bool EnableTotalRecordCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemQuery" /> class.
|
||||
/// </summary>
|
||||
@ -306,6 +308,8 @@ namespace MediaBrowser.Model.Querying
|
||||
|
||||
VideoTypes = new VideoType[] { };
|
||||
|
||||
EnableTotalRecordCount = true;
|
||||
|
||||
Artists = new string[] { };
|
||||
Studios = new string[] { };
|
||||
|
||||
|
@ -145,11 +145,15 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
bool hasRefreshedMetadata = true;
|
||||
bool hasRefreshedImages = true;
|
||||
var requiresRefresh = false;
|
||||
|
||||
// Next run metadata providers
|
||||
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
|
||||
{
|
||||
var providers = GetProviders(item, refreshResult, refreshOptions)
|
||||
// TODO: If this returns true, should we instead just change metadata refresh mode to Full?
|
||||
requiresRefresh = item.RequiresRefresh();
|
||||
|
||||
var providers = GetProviders(item, refreshResult, refreshOptions, requiresRefresh)
|
||||
.ToList();
|
||||
|
||||
var dateLastRefresh = EnableDateLastRefreshed(item)
|
||||
@ -217,11 +221,11 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
var isFirstRefresh = GetLastRefreshDate(item) == default(DateTime);
|
||||
|
||||
var beforeSaveResult = await BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh, updateType).ConfigureAwait(false);
|
||||
var beforeSaveResult = await BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh, updateType).ConfigureAwait(false);
|
||||
updateType = updateType | beforeSaveResult;
|
||||
|
||||
// Save if changes were made, or it's never been saved before
|
||||
if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata)
|
||||
if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh)
|
||||
{
|
||||
// If any of these properties are set then make sure the updateType is not None, just to force everything to save
|
||||
if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata)
|
||||
@ -461,11 +465,8 @@ namespace MediaBrowser.Providers.Manager
|
||||
/// <summary>
|
||||
/// Gets the providers.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="status">The status.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>IEnumerable{`0}.</returns>
|
||||
protected IEnumerable<IMetadataProvider> GetProviders(IHasMetadata item, MetadataStatus status, MetadataRefreshOptions options)
|
||||
protected IEnumerable<IMetadataProvider> GetProviders(IHasMetadata item, MetadataStatus status, MetadataRefreshOptions options, bool requiresRefresh)
|
||||
{
|
||||
// Get providers to refresh
|
||||
var providers = ((ProviderManager)ProviderManager).GetMetadataProviders<TItemType>(item).ToList();
|
||||
@ -475,7 +476,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
: status.DateLastMetadataRefresh ?? default(DateTime);
|
||||
|
||||
// Run all if either of these flags are true
|
||||
var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime) || item.RequiresRefresh();
|
||||
var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime) || requiresRefresh;
|
||||
|
||||
if (!runAllProviders)
|
||||
{
|
||||
@ -668,12 +669,6 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
// If a local provider fails, consider that a failure
|
||||
refreshResult.ErrorMessage = ex.Message;
|
||||
|
||||
if (options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
|
||||
{
|
||||
// If the local provider fails don't continue with remote providers because the user's saved metadata could be lost
|
||||
//return refreshResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
if (!hasSeason)
|
||||
{
|
||||
await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
|
||||
await AddSeason(series, seasonNumber, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
hasChanges = true;
|
||||
}
|
||||
@ -83,7 +83,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
if (!hasSeason)
|
||||
{
|
||||
await AddSeason(series, null, cancellationToken).ConfigureAwait(false);
|
||||
await AddSeason(series, null, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
hasChanges = true;
|
||||
}
|
||||
@ -95,12 +95,9 @@ namespace MediaBrowser.Providers.TV
|
||||
/// <summary>
|
||||
/// Adds the season.
|
||||
/// </summary>
|
||||
/// <param name="series">The series.</param>
|
||||
/// <param name="seasonNumber">The season number.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Season}.</returns>
|
||||
public async Task<Season> AddSeason(Series series,
|
||||
int? seasonNumber,
|
||||
bool isVirtualItem,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var seasonName = seasonNumber == 0 ?
|
||||
@ -113,7 +110,8 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
Name = seasonName,
|
||||
IndexNumber = seasonNumber,
|
||||
Id = _libraryManager.GetNewItemId((series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName), typeof(Season))
|
||||
Id = _libraryManager.GetNewItemId((series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName), typeof(Season)),
|
||||
IsVirtualItem = isVirtualItem
|
||||
};
|
||||
|
||||
season.SetParent(series);
|
||||
|
@ -418,7 +418,7 @@ namespace MediaBrowser.Providers.TV
|
||||
if (season == null)
|
||||
{
|
||||
var provider = new DummySeasonProvider(_config, _logger, _localization, _libraryManager, _fileSystem);
|
||||
season = await provider.AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
|
||||
season = await provider.AddSeason(series, seasonNumber, true, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var name = string.Format("Episode {0}", episodeNumber.ToString(_usCulture));
|
||||
|
@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
var episodes = item.GetEpisodes().ToList();
|
||||
updateType |= SavePremiereDate(item, episodes);
|
||||
updateType |= SaveIsMissing(item, episodes);
|
||||
updateType |= SaveIsVirtualItem(item, episodes);
|
||||
}
|
||||
|
||||
return updateType;
|
||||
@ -67,13 +67,13 @@ namespace MediaBrowser.Providers.TV
|
||||
return ItemUpdateType.None;
|
||||
}
|
||||
|
||||
private ItemUpdateType SaveIsMissing(Season item, List<Episode> episodes)
|
||||
private ItemUpdateType SaveIsVirtualItem(Season item, List<Episode> episodes)
|
||||
{
|
||||
var isMissing = item.LocationType == LocationType.Virtual && episodes.All(i => i.IsMissingEpisode);
|
||||
var isVirtualItem = item.LocationType == LocationType.Virtual && (episodes.Count == 0 || episodes.All(i => i.LocationType == LocationType.Virtual));
|
||||
|
||||
if (item.IsMissingSeason != isMissing)
|
||||
if (item.IsVirtualItem != isVirtualItem)
|
||||
{
|
||||
item.IsMissingSeason = isMissing;
|
||||
item.IsVirtualItem = isVirtualItem;
|
||||
return ItemUpdateType.MetadataEdit;
|
||||
}
|
||||
|
||||
|
@ -1448,8 +1448,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
// 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 user.RootFolder
|
||||
.GetChildren(user, true)
|
||||
.OfType<CollectionFolder>()
|
||||
.Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase))
|
||||
.Where(i => user.IsFolderGrouped(i.Id))
|
||||
.SelectMany(i => GetTopParentsForQuery(i, user));
|
||||
}
|
||||
return new BaseItem[] { };
|
||||
}
|
||||
|
@ -30,7 +30,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user)
|
||||
{
|
||||
var genres = user.RootFolder
|
||||
.GetRecursiveChildren(user, i => i is Audio)
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.Where(i => i.HasAnyArtist(artist.Name))
|
||||
.SelectMany(i => i.Genres)
|
||||
@ -43,7 +46,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
|
||||
{
|
||||
var genres = item
|
||||
.GetRecursiveChildren(user, i => i is Audio)
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.Concat(item.Genres)
|
||||
@ -55,7 +61,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
|
||||
{
|
||||
var genres = item
|
||||
.GetRecursiveChildren(user, i => i is Audio)
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] {typeof(Audio).Name}
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.Concat(item.Genres)
|
||||
@ -67,7 +76,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
|
||||
{
|
||||
var genres = item
|
||||
.GetRecursiveChildren(user, i => i is Audio)
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.Concat(item.Genres)
|
||||
|
@ -115,17 +115,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
var recordingFolders = GetRecordingFolders();
|
||||
|
||||
var defaultRecordingPath = DefaultRecordingPath;
|
||||
if (!recordingFolders.Any(i => i.Locations.Contains(defaultRecordingPath, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
RemovePathFromLibrary(defaultRecordingPath);
|
||||
}
|
||||
|
||||
var virtualFolders = _libraryManager.GetVirtualFolders()
|
||||
.ToList();
|
||||
|
||||
var allExistingPaths = virtualFolders.SelectMany(i => i.Locations).ToList();
|
||||
|
||||
var pathsAdded = new List<string>();
|
||||
|
||||
foreach (var recordingFolder in recordingFolders)
|
||||
{
|
||||
var pathsToCreate = recordingFolder.Locations
|
||||
@ -145,11 +141,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
_logger.ErrorException("Error creating virtual folder", ex);
|
||||
}
|
||||
|
||||
pathsAdded.AddRange(pathsToCreate);
|
||||
}
|
||||
|
||||
var config = GetConfiguration();
|
||||
|
||||
var pathsToRemove = config.MediaLocationsCreated
|
||||
.Except(recordingFolders.SelectMany(i => i.Locations))
|
||||
.ToList();
|
||||
|
||||
if (pathsAdded.Count > 0 || pathsToRemove.Count > 0)
|
||||
{
|
||||
pathsAdded.InsertRange(0, config.MediaLocationsCreated);
|
||||
config.MediaLocationsCreated = pathsAdded.Except(pathsToRemove).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
_config.SaveConfiguration("livetv", config);
|
||||
}
|
||||
|
||||
foreach (var path in pathsToRemove)
|
||||
{
|
||||
RemovePathFromLibrary(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemovePathFromLibrary(string path)
|
||||
{
|
||||
_logger.Debug("Removing path from library: {0}", path);
|
||||
|
||||
var requiresRefresh = false;
|
||||
var virtualFolders = _libraryManager.GetVirtualFolders()
|
||||
.ToList();
|
||||
|
@ -527,6 +527,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, Guid parentFolderId, CancellationToken cancellationToken)
|
||||
{
|
||||
var isNew = false;
|
||||
var forceUpdate = false;
|
||||
|
||||
var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id);
|
||||
|
||||
@ -576,10 +577,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath))
|
||||
{
|
||||
item.SetImagePath(ImageType.Primary, channelInfo.ImagePath);
|
||||
forceUpdate = true;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(channelInfo.ImageUrl))
|
||||
{
|
||||
item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl);
|
||||
forceUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,9 +591,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
item.Name = channelInfo.Name;
|
||||
}
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else if (forceUpdate)
|
||||
{
|
||||
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
|
||||
{
|
||||
ForceSave = isNew
|
||||
ForceSave = isNew || forceUpdate
|
||||
|
||||
}, cancellationToken);
|
||||
|
||||
@ -1398,16 +1410,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
.Where(i => i.IsVisibleStandalone(user))
|
||||
.ToList();
|
||||
|
||||
var items = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||
if (folders.Count == 0)
|
||||
{
|
||||
return new QueryResult<BaseItem>();
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||
{
|
||||
MediaTypes = new[] { MediaType.Video },
|
||||
Recursive = true,
|
||||
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
|
||||
IsFolder = false,
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
||||
Limit = Math.Min(10, query.Limit ?? int.MaxValue)
|
||||
Limit = Math.Min(200, query.Limit ?? int.MaxValue),
|
||||
SortBy = new[] { ItemSortBy.DateCreated },
|
||||
SortOrder = SortOrder.Descending
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)
|
||||
|
@ -55,9 +55,9 @@
|
||||
<Reference Include="Interfaces.IO">
|
||||
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MediaBrowser.Naming, Version=1.0.5917.1514, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.49\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
|
||||
<Reference Include="MediaBrowser.Naming, Version=1.0.5981.21615, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.50\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||
@ -68,8 +68,8 @@
|
||||
<Reference Include="ServiceStack.Api.Swagger">
|
||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=3.1.3.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SocketHttpListener, Version=1.0.5955.1537, Culture=neutral, processorArchitecture=MSIL">
|
||||
|
@ -81,10 +81,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
private IDbCommand _deleteUserDataKeysCommand;
|
||||
private IDbCommand _saveUserDataKeysCommand;
|
||||
|
||||
private IDbCommand _deleteItemValuesCommand;
|
||||
private IDbCommand _saveItemValuesCommand;
|
||||
|
||||
private IDbCommand _updateInheritedRatingCommand;
|
||||
private IDbCommand _updateInheritedTagsCommand;
|
||||
|
||||
public const int LatestSchemaVersion = 78;
|
||||
public const int LatestSchemaVersion = 79;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
|
||||
@ -136,6 +139,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
"create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT, PRIMARY KEY (ItemId, UserDataKey))",
|
||||
"create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)",
|
||||
|
||||
"create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT)",
|
||||
"create index if not exists idx_ItemValues on ItemValues(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)",
|
||||
@ -232,6 +238,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
_connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text");
|
||||
_connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME");
|
||||
_connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text");
|
||||
_connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT");
|
||||
|
||||
_connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT");
|
||||
|
||||
@ -353,7 +360,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
"DateLastMediaAdded",
|
||||
"Album",
|
||||
"CriticRating",
|
||||
"CriticRatingSummary"
|
||||
"CriticRatingSummary",
|
||||
"IsVirtualItem"
|
||||
};
|
||||
|
||||
private readonly string[] _mediaStreamSaveColumns =
|
||||
@ -468,7 +476,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
"OriginalTitle",
|
||||
"PrimaryVersionId",
|
||||
"DateLastMediaAdded",
|
||||
"Album"
|
||||
"Album",
|
||||
"IsVirtualItem"
|
||||
};
|
||||
_saveItemCommand = _connection.CreateCommand();
|
||||
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
|
||||
@ -565,6 +574,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey");
|
||||
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority");
|
||||
|
||||
// item values
|
||||
_deleteItemValuesCommand = _connection.CreateCommand();
|
||||
_deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id";
|
||||
_deleteItemValuesCommand.Parameters.Add(_deleteItemValuesCommand, "@Id");
|
||||
|
||||
_saveItemValuesCommand = _connection.CreateCommand();
|
||||
_saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)";
|
||||
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@ItemId");
|
||||
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type");
|
||||
_saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -722,7 +742,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
_saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed;
|
||||
}
|
||||
|
||||
_saveItemCommand.GetParameter(index++).Value = item.DateLastSaved;
|
||||
if (item.DateLastSaved == default(DateTime))
|
||||
{
|
||||
_saveItemCommand.GetParameter(index++).Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_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());
|
||||
@ -841,6 +869,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
|
||||
_saveItemCommand.GetParameter(index++).Value = item.Album;
|
||||
|
||||
var season = item as Season;
|
||||
if (season != null && season.IsVirtualItem.HasValue)
|
||||
{
|
||||
_saveItemCommand.GetParameter(index++).Value = season.IsVirtualItem.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveItemCommand.GetParameter(index++).Value = null;
|
||||
}
|
||||
|
||||
_saveItemCommand.Transaction = transaction;
|
||||
|
||||
_saveItemCommand.ExecuteNonQuery();
|
||||
@ -851,6 +889,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
}
|
||||
|
||||
UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction);
|
||||
UpdateItemValues(item.Id, GetItemValues(item), transaction);
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
@ -1255,6 +1294,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
item.CriticRatingSummary = reader.GetString(57);
|
||||
}
|
||||
|
||||
var season = item as Season;
|
||||
if (season != null && !reader.IsDBNull(58))
|
||||
{
|
||||
season.IsVirtualItem = reader.GetBoolean(58);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -1661,7 +1706,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
{
|
||||
var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds;
|
||||
|
||||
if (elapsed >= 500)
|
||||
if (elapsed >= 400)
|
||||
{
|
||||
Logger.Debug("{2} query time (slow): {0}ms. Query: {1}",
|
||||
Convert.ToInt32(elapsed),
|
||||
@ -1795,7 +1840,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
}).ToArray());
|
||||
}
|
||||
|
||||
private Tuple<string,bool> MapOrderByField(string name)
|
||||
private Tuple<string, bool> MapOrderByField(string name)
|
||||
{
|
||||
if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@ -1838,6 +1883,14 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
{
|
||||
return new Tuple<string, bool>("DateLastMediaAdded", false);
|
||||
}
|
||||
if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Tuple<string, bool>("(select value from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false);
|
||||
}
|
||||
if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Tuple<string, bool>("(select value from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false);
|
||||
}
|
||||
|
||||
return new Tuple<string, bool>(name, false);
|
||||
}
|
||||
@ -2405,17 +2458,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
cmd.Parameters.Add(cmd, "@IsFavorite", DbType.Boolean).Value = query.IsFavorite.Value;
|
||||
}
|
||||
|
||||
if (query.IsPlayed.HasValue)
|
||||
if (EnableJoinUserData(query))
|
||||
{
|
||||
if (query.IsPlayed.Value)
|
||||
if (query.IsPlayed.HasValue)
|
||||
{
|
||||
whereClauses.Add("(played=@IsPlayed)");
|
||||
if (query.IsPlayed.Value)
|
||||
{
|
||||
whereClauses.Add("(played=@IsPlayed)");
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("(played is null or played=@IsPlayed)");
|
||||
}
|
||||
cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("(played is null or played=@IsPlayed)");
|
||||
}
|
||||
cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value;
|
||||
}
|
||||
|
||||
if (query.IsResumable.HasValue)
|
||||
@ -2430,6 +2486,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
}
|
||||
}
|
||||
|
||||
if (query.ArtistNames.Length > 0)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
var index = 0;
|
||||
foreach (var artist in query.ArtistNames)
|
||||
{
|
||||
clauses.Add("@ArtistName" + index + " in (select value from itemvalues where ItemId=Guid and Type <= 1)");
|
||||
cmd.Parameters.Add(cmd, "@ArtistName" + index, DbType.String).Value = artist;
|
||||
index++;
|
||||
}
|
||||
var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")";
|
||||
whereClauses.Add(clause);
|
||||
}
|
||||
|
||||
if (query.Genres.Length > 0)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
@ -2967,6 +3037,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
_deleteUserDataKeysCommand.Transaction = transaction;
|
||||
_deleteUserDataKeysCommand.ExecuteNonQuery();
|
||||
|
||||
// Delete item values
|
||||
_deleteItemValuesCommand.GetParameter(0).Value = id;
|
||||
_deleteItemValuesCommand.Transaction = transaction;
|
||||
_deleteItemValuesCommand.ExecuteNonQuery();
|
||||
|
||||
// Delete the item
|
||||
_deleteItemCommand.GetParameter(0).Value = id;
|
||||
_deleteItemCommand.Transaction = transaction;
|
||||
@ -3159,6 +3234,56 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tuple<int, string>> GetItemValues(BaseItem item)
|
||||
{
|
||||
var list = new List<Tuple<int, string>>();
|
||||
|
||||
var hasArtist = item as IHasArtist;
|
||||
if (hasArtist != null)
|
||||
{
|
||||
list.AddRange(hasArtist.Artists.Select(i => new Tuple<int, string>(0, i)));
|
||||
}
|
||||
|
||||
var hasAlbumArtist = item as IHasAlbumArtist;
|
||||
if (hasAlbumArtist != null)
|
||||
{
|
||||
list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple<int, string>(1, i)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void UpdateItemValues(Guid itemId, List<Tuple<int, string>> values, IDbTransaction transaction)
|
||||
{
|
||||
if (itemId == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentNullException("itemId");
|
||||
}
|
||||
|
||||
if (values == null)
|
||||
{
|
||||
throw new ArgumentNullException("keys");
|
||||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
// First delete
|
||||
_deleteItemValuesCommand.GetParameter(0).Value = itemId;
|
||||
_deleteItemValuesCommand.Transaction = transaction;
|
||||
|
||||
_deleteItemValuesCommand.ExecuteNonQuery();
|
||||
|
||||
foreach (var pair in values)
|
||||
{
|
||||
_saveItemValuesCommand.GetParameter(0).Value = itemId;
|
||||
_saveItemValuesCommand.GetParameter(1).Value = pair.Item1;
|
||||
_saveItemValuesCommand.GetParameter(2).Value = pair.Item2;
|
||||
_saveItemValuesCommand.Transaction = transaction;
|
||||
|
||||
_saveItemValuesCommand.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUserDataKeys(Guid itemId, List<string> keys, IDbTransaction transaction)
|
||||
{
|
||||
if (itemId == Guid.Empty)
|
||||
|
@ -4,10 +4,10 @@
|
||||
<package id="Emby.XmlTv" version="1.0.0.48" targetFramework="net45" />
|
||||
<package id="ini-parser" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
|
||||
<package id="MediaBrowser.Naming" version="1.0.0.49" targetFramework="net45" />
|
||||
<package id="MediaBrowser.Naming" version="1.0.0.50" targetFramework="net45" />
|
||||
<package id="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
|
||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.1.3" targetFramework="net45" />
|
||||
<package id="SimpleInjector" version="3.1.4" targetFramework="net45" />
|
||||
<package id="SocketHttpListener" version="1.0.0.30" targetFramework="net45" />
|
||||
</packages>
|
@ -107,9 +107,6 @@
|
||||
<Content Include="dashboard-ui\components\chromecasthelpers.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\bower_components\fastclick\lib\fastclick.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\components\favoriteitems.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@ -1686,6 +1683,9 @@
|
||||
<None Include="dashboard-ui\strings\id.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="dashboard-ui\strings\sk.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="dashboard-ui\strings\zh-HK.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common.Internal</id>
|
||||
<version>3.0.647</version>
|
||||
<version>3.0.648</version>
|
||||
<title>MediaBrowser.Common.Internal</title>
|
||||
<authors>Luke</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
@ -12,9 +12,9 @@
|
||||
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
|
||||
<copyright>Copyright © Emby 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.647" />
|
||||
<dependency id="NLog" version="4.3.1" />
|
||||
<dependency id="SimpleInjector" version="3.1.3" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.648" />
|
||||
<dependency id="NLog" version="4.3.4" />
|
||||
<dependency id="SimpleInjector" version="3.1.4" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common</id>
|
||||
<version>3.0.647</version>
|
||||
<version>3.0.648</version>
|
||||
<title>MediaBrowser.Common</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Model.Signed</id>
|
||||
<version>3.0.647</version>
|
||||
<title>MediaBrowser.Model - Signed Edition</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
||||
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains common model objects and interfaces used by all Emby solutions.</description>
|
||||
<copyright>Copyright © Emby 2013</copyright>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="dllssigned\net45\MediaBrowser.Model.dll" target="lib\net45\MediaBrowser.Model.dll" />
|
||||
</files>
|
||||
</package>
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Server.Core</id>
|
||||
<version>3.0.647</version>
|
||||
<version>3.0.648</version>
|
||||
<title>Media Browser.Server.Core</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
@ -12,7 +12,7 @@
|
||||
<description>Contains core components required to build plugins for Emby Server.</description>
|
||||
<copyright>Copyright © Emby 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.647" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.648" />
|
||||
<dependency id="Interfaces.IO" version="1.0.0.5" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
Loading…
Reference in New Issue
Block a user