Merge branch 'beta'

This commit is contained in:
Luke Pulverenti 2016-05-21 00:49:17 -04:00
commit b253d26aba
44 changed files with 529 additions and 373 deletions

View file

@ -103,7 +103,8 @@ namespace MediaBrowser.Api
User = user, User = user,
MediaTypes = request.GetMediaTypes(), MediaTypes = request.GetMediaTypes(),
IncludeItemTypes = request.GetIncludeItemTypes(), IncludeItemTypes = request.GetIncludeItemTypes(),
Recursive = true Recursive = true,
EnableTotalRecordCount = false
}; };
return query; return query;

View file

@ -162,7 +162,10 @@ namespace MediaBrowser.Api
var items = user == null ? var items = user == null ?
system.GetRecursiveChildren(i => i is Game) : 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(); var games = items.Cast<Game>().ToList();

View file

@ -65,11 +65,7 @@ namespace MediaBrowser.Api
public void Post(ReportStartupWizardComplete request) public void Post(ReportStartupWizardComplete request)
{ {
_config.Configuration.IsStartupWizardCompleted = true; _config.Configuration.IsStartupWizardCompleted = true;
_config.Configuration.EnableLocalizedGuids = true; SetWizardFinishValues(_config.Configuration);
_config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.EnableDateLastRefresh = true;
_config.Configuration.EnableStandaloneMusicKeys = true;
_config.Configuration.EnableCaseSensitiveItemIds = true;
_config.SaveConfiguration(); _config.SaveConfiguration();
} }
@ -111,6 +107,15 @@ namespace MediaBrowser.Api
return result; 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) public void Post(UpdateStartupConfiguration request)
{ {
_config.Configuration.UICulture = request.UICulture; _config.Configuration.UICulture = request.UICulture;

View file

@ -415,21 +415,10 @@ namespace MediaBrowser.Api
private IEnumerable<Season> FilterVirtualSeasons(GetSeasons request, IEnumerable<Season> items) 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) if (request.IsMissing.HasValue)
{ {
var val = request.IsMissing.Value; var val = request.IsMissing.Value;
items = items.Where(i => (i.IsMissingSeason ?? false) == val); items = items.Where(i => (i.IsMissingSeason) == val);
} }
if (request.IsVirtualUnaired.HasValue) if (request.IsVirtualUnaired.HasValue)

View file

@ -121,6 +121,13 @@ namespace MediaBrowser.Api.UserLibrary
var includeItemTypes = request.GetIncludeItemTypes(); var includeItemTypes = request.GetIncludeItemTypes();
var mediaTypes = request.GetMediaTypes(); 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); Func<BaseItem, bool> filter = i => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes);
if (parentItem.IsFolder) if (parentItem.IsFolder)
@ -130,7 +137,7 @@ namespace MediaBrowser.Api.UserLibrary
if (!string.IsNullOrWhiteSpace(request.UserId)) if (!string.IsNullOrWhiteSpace(request.UserId))
{ {
items = request.Recursive ? items = request.Recursive ?
folder.GetRecursiveChildren(user, filter) : folder.GetRecursiveChildren(user, query) :
folder.GetChildren(user, true).Where(filter); folder.GetChildren(user, true).Where(filter);
} }
else else

View file

@ -138,25 +138,19 @@ namespace MediaBrowser.Api.UserLibrary
if (request.Recursive) if (request.Recursive)
{ {
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false); return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
return result;
} }
if (user == null) if (user == null)
{ {
var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false); return await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
return result;
} }
var userRoot = item as UserRootFolder; var userRoot = item as UserRootFolder;
if (userRoot == null) if (userRoot == null)
{ {
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false); return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
return result;
} }
IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true); IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);

View file

@ -55,7 +55,7 @@
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath> <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <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> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
@ -65,8 +65,8 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath> <HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference> </Reference>
<Reference Include="SimpleInjector, Version=3.1.3.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll</HintPath> <HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

View file

@ -2,7 +2,7 @@
<packages> <packages>
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
<package id="morelinq" version="1.4.0" 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="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> </packages>

View file

@ -64,10 +64,37 @@ namespace MediaBrowser.Controller.Entities
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) 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; var path = ContainingFolderPath;
@ -100,7 +127,11 @@ namespace MediaBrowser.Controller.Entities
args.FileSystemDictionary = fileSystemDictionary; args.FileSystemDictionary = fileSystemDictionary;
} }
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
if (setPhysicalLocations)
{
PhysicalLocationsList = args.PhysicalLocations.ToList(); PhysicalLocationsList = args.PhysicalLocations.ToList();
}
return args; return args;
} }

View file

@ -56,38 +56,23 @@ namespace MediaBrowser.Controller.Entities.Audio
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{ {
var itemByNameFilter = GetItemFilter(); if (query.IncludeItemTypes.Length == 0)
if (query.User != null)
{ {
return query.User.RootFolder query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
.GetRecursiveChildren(query.User, i => query.ArtistNames = new[] { Name };
{
if (query.IsFolder.HasValue)
{
if (query.IsFolder.Value != i.IsFolder)
{
return false;
}
}
return itemByNameFilter(i);
});
} }
return LibraryManager.RootFolder // Need this for now since the artist filter isn't yet supported by the db
.GetRecursiveChildren(i => if (ConfigurationManager.Configuration.SchemaVersion < 79)
{ {
if (query.IsFolder.HasValue) var filter = GetItemFilter();
{ return LibraryManager.GetItemList(query).Where(filter);
if (query.IsFolder.Value != i.IsFolder)
{
return false;
}
}
return itemByNameFilter(i);
});
} }
return LibraryManager.GetItemList(query);
}
[IgnoreDataMember]
protected override IEnumerable<BaseItem> ActualChildren protected override IEnumerable<BaseItem> ActualChildren
{ {
get get

View file

@ -23,19 +23,6 @@ namespace MediaBrowser.Controller.Entities
PhysicalLocationsList = new List<string>(); 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] [IgnoreDataMember]
protected override bool SupportsShortcutChildren protected override bool SupportsShortcutChildren
{ {
@ -83,7 +70,34 @@ namespace MediaBrowser.Controller.Entities
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) 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) internal override bool IsValidFromResolver(BaseItem newItem)
@ -101,7 +115,7 @@ namespace MediaBrowser.Controller.Entities
return base.IsValidFromResolver(newItem); return base.IsValidFromResolver(newItem);
} }
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService) private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
{ {
var path = ContainingFolderPath; var path = ContainingFolderPath;
@ -135,7 +149,11 @@ namespace MediaBrowser.Controller.Entities
args.FileSystemDictionary = fileSystemDictionary; args.FileSystemDictionary = fileSystemDictionary;
} }
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
if (setPhysicalLocations)
{
PhysicalLocationsList = args.PhysicalLocations.ToList(); PhysicalLocationsList = args.PhysicalLocations.ToList();
}
return args; return args;
} }
@ -153,15 +171,6 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns> /// <returns>Task.</returns>
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) 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); 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... /// Our children are actually just references to the ones in the physical root...
/// </summary> /// </summary>
/// <value>The actual children.</value> /// <value>The actual children.</value>
[IgnoreDataMember]
protected override IEnumerable<BaseItem> ActualChildren protected override IEnumerable<BaseItem> ActualChildren
{ {
get { return GetActualChildren(); } get { return GetActualChildren(); }

View file

@ -126,19 +126,6 @@ namespace MediaBrowser.Controller.Entities
/// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value>
public bool IsRoot { get; set; } 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; } public virtual List<LinkedChild> LinkedChildren { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
@ -285,6 +272,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets the actual children. /// Gets the actual children.
/// </summary> /// </summary>
/// <value>The actual children.</value> /// <value>The actual children.</value>
[IgnoreDataMember]
protected virtual IEnumerable<BaseItem> ActualChildren protected virtual IEnumerable<BaseItem> ActualChildren
{ {
get get
@ -749,7 +737,7 @@ namespace MediaBrowser.Controller.Entities
{ {
var user = query.User; var user = query.User;
if (RequiresPostFiltering(query)) if (!query.ForceDirect && RequiresPostFiltering(query))
{ {
IEnumerable<BaseItem> items; IEnumerable<BaseItem> items;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@ -760,7 +748,7 @@ namespace MediaBrowser.Controller.Entities
} }
else else
{ {
items = GetRecursiveChildren(user, filter); items = GetRecursiveChildren(user, query);
} }
return PostFilterAndSort(items, query); return PostFilterAndSort(items, query);
@ -817,11 +805,9 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
} }
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
if (ConfigurationManager.Configuration.SchemaVersion < 79)
{ {
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
return true;
}
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase)) if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
{ {
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist"); Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
@ -832,6 +818,13 @@ namespace MediaBrowser.Controller.Entities
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist"); Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
return true; 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.Budget, StringComparer.OrdinalIgnoreCase)) if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
{ {
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget"); Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
@ -1109,11 +1102,14 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
if (ConfigurationManager.Configuration.SchemaVersion < 79)
{
if (query.ArtistNames.Length > 0) if (query.ArtistNames.Length > 0)
{ {
Logger.Debug("Query requires post-filtering due to ArtistNames"); Logger.Debug("Query requires post-filtering due to ArtistNames");
return true; return true;
} }
}
return false; return false;
} }
@ -1178,7 +1174,7 @@ namespace MediaBrowser.Controller.Entities
else else
{ {
items = query.Recursive items = query.Recursive
? GetRecursiveChildren(user, filter) ? GetRecursiveChildren(user, query)
: GetChildren(user, true).Where(filter); : GetChildren(user, true).Where(filter);
} }
@ -1215,19 +1211,14 @@ namespace MediaBrowser.Controller.Entities
/// <summary> /// <summary>
/// Adds the children to list. /// Adds the children to list.
/// </summary> /// </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> /// <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)) foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
{ {
if (child.IsVisible(user)) if (child.IsVisible(user))
{ {
if (filter == null || filter(child)) if (query == null || UserViewBuilder.FilterItem(child, query))
{ {
result[child.Id] = child; result[child.Id] = child;
} }
@ -1236,7 +1227,7 @@ namespace MediaBrowser.Controller.Entities
{ {
var folder = (Folder)child; 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 (child.IsVisible(user))
{ {
if (filter == null || filter(child)) if (query == null || UserViewBuilder.FilterItem(child, query))
{ {
result[child.Id] = child; result[child.Id] = child;
} }
@ -1265,10 +1256,10 @@ namespace MediaBrowser.Controller.Entities
/// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentNullException"></exception>
public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) 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) if (user == null)
{ {
@ -1277,7 +1268,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>(); var result = new Dictionary<Guid, BaseItem>();
AddChildren(user, true, result, true, filter); AddChildren(user, true, result, true, query);
return result.Values; return result.Values;
} }
@ -1303,7 +1294,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary> /// <summary>
/// Adds the children to list. /// Adds the children to list.
/// </summary> /// </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) foreach (var child in Children)
{ {
@ -1534,13 +1525,12 @@ namespace MediaBrowser.Controller.Entities
User = user, User = user,
Recursive = true, Recursive = true,
IsFolder = false, 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); var itemsResult = await GetItems(query).ConfigureAwait(false);
@ -1562,7 +1552,8 @@ namespace MediaBrowser.Controller.Entities
{ {
User = user, User = user,
Recursive = true, Recursive = true,
IsFolder = false IsFolder = false,
EnableTotalRecordCount = false
}).ConfigureAwait(false); }).ConfigureAwait(false);
@ -1578,7 +1569,8 @@ namespace MediaBrowser.Controller.Entities
{ {
Recursive = true, Recursive = true,
IsFolder = false, IsFolder = false,
ExcludeLocationTypes = new[] { LocationType.Virtual } ExcludeLocationTypes = new[] { LocationType.Virtual },
EnableTotalRecordCount = false
}).Result; }).Result;
@ -1630,7 +1622,8 @@ namespace MediaBrowser.Controller.Entities
{ {
Recursive = true, Recursive = true,
IsFolder = false, IsFolder = false,
ExcludeLocationTypes = new[] { LocationType.Virtual } ExcludeLocationTypes = new[] { LocationType.Virtual },
EnableTotalRecordCount = false
}).Result; }).Result;

View file

@ -15,12 +15,6 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems); IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
/// <summary>
/// Gets the item filter.
/// </summary>
/// <returns>Func&lt;BaseItem, System.Boolean&gt;.</returns>
Func<BaseItem, bool> GetItemFilter();
IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query); IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query);
} }

View file

@ -19,8 +19,6 @@ namespace MediaBrowser.Controller.Entities
public User User { get; set; } public User User { get; set; }
public Func<BaseItem, bool> Filter { get; set; }
public bool? IsFolder { get; set; } public bool? IsFolder { get; set; }
public bool? IsFavorite { get; set; } public bool? IsFavorite { get; set; }
public bool? IsFavoriteOrLiked { get; set; } public bool? IsFavoriteOrLiked { get; set; }
@ -138,6 +136,7 @@ namespace MediaBrowser.Controller.Entities
public bool GroupByPresentationUniqueKey { get; set; } public bool GroupByPresentationUniqueKey { get; set; }
public bool EnableTotalRecordCount { get; set; } public bool EnableTotalRecordCount { get; set; }
public bool ForceDirect { get; set; }
public InternalItemsQuery() public InternalItemsQuery()
{ {

View file

@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (!result) if (!result)
{ {
if (!IsMissingSeason.HasValue) if (!IsVirtualItem.HasValue)
{ {
return true; return true;
} }
@ -144,18 +144,23 @@ namespace MediaBrowser.Controller.Entities.TV
} }
[IgnoreDataMember] [IgnoreDataMember]
public bool? IsMissingSeason { get; set; } public bool? IsVirtualItem { get; set; }
[IgnoreDataMember]
public bool IsMissingSeason
{
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; }
}
[IgnoreDataMember] [IgnoreDataMember]
public bool IsVirtualUnaired public bool IsVirtualUnaired
{ {
get { return LocationType == LocationType.Virtual && IsUnaired; } get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; }
} }
[IgnoreDataMember] private bool DetectIsVirtualItem()
public bool IsMissingOrVirtualUnaired
{ {
get { return (IsMissingSeason ?? false) || (LocationType == LocationType.Virtual && IsUnaired); } return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual);
} }
[IgnoreDataMember] [IgnoreDataMember]
@ -319,10 +324,6 @@ namespace MediaBrowser.Controller.Entities.TV
{ {
var hasChanges = base.BeforeMetadataRefresh(); 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);
@ -333,7 +334,6 @@ namespace MediaBrowser.Controller.Entities.TV
hasChanges = true; hasChanges = true;
} }
} }
}
return hasChanges; return hasChanges;
} }

View file

@ -238,21 +238,14 @@ namespace MediaBrowser.Controller.Entities.TV
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>(); seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
} }
if (!includeMissingSeasons && !includeVirtualUnaired)
{
seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired);
}
else
{
if (!includeMissingSeasons) if (!includeMissingSeasons)
{ {
seasons = seasons.Where(i => !(i.IsMissingSeason ?? false)); seasons = seasons.Where(i => !(i.IsMissingSeason));
} }
if (!includeVirtualUnaired) if (!includeVirtualUnaired)
{ {
seasons = seasons.Where(i => !i.IsVirtualUnaired); seasons = seasons.Where(i => !i.IsVirtualUnaired);
} }
}
return seasons; return seasons;
} }
@ -381,14 +374,18 @@ namespace MediaBrowser.Controller.Entities.TV
} }
else else
{ {
episodes = GetRecursiveChildren(user, i => i is Episode) episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
.Cast<Episode>(); {
IncludeItemTypes = new[] { typeof(Episode).Name }
}).Cast<Episode>();
} }
} }
else else
{ {
episodes = GetRecursiveChildren(user, i => i is Episode) episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
.Cast<Episode>(); {
IncludeItemTypes = new[] { typeof(Episode).Name }
}).Cast<Episode>();
} }
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons); episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);

View file

@ -305,14 +305,7 @@ namespace MediaBrowser.Controller.Entities
public bool IsFolderGrouped(Guid id) public bool IsFolderGrouped(Guid id)
{ {
var config = Configuration; return Configuration.GroupedFolders.Select(i => new Guid(i)).Contains(id);
if (config.ExcludeFoldersFromGrouping != null)
{
return !config.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).Contains(id);
}
return config.GroupedFolders.Select(i => new Guid(i)).Contains(id);
} }
[IgnoreDataMember] [IgnoreDataMember]

View file

@ -64,15 +64,6 @@ namespace MediaBrowser.Controller.Entities
return list; 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() public override bool BeforeMetadataRefresh()
{ {
var hasChanges = base.BeforeMetadataRefresh(); var hasChanges = base.BeforeMetadataRefresh();

View file

@ -66,7 +66,8 @@ namespace MediaBrowser.Controller.Entities
{ {
var result = GetItems(new InternalItemsQuery var result = GetItems(new InternalItemsQuery
{ {
User = user User = user,
EnableTotalRecordCount = false
}).Result; }).Result;
@ -83,17 +84,19 @@ namespace MediaBrowser.Controller.Entities
return true; 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 var result = GetItems(new InternalItemsQuery
{ {
User = user, User = user,
Recursive = true, Recursive = true,
Filter = filter EnableTotalRecordCount = false,
ForceDirect = true
}).Result; }).Result;
return result.Items; return result.Items.Where(i => UserViewBuilder.FilterItem(i, query));
} }
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)

View file

@ -128,7 +128,11 @@ namespace MediaBrowser.Controller.Entities
{ {
if (query.Recursive) 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); return GetResult(queryParent.GetChildren(user, true), queryParent, query);
} }
@ -251,7 +255,6 @@ namespace MediaBrowser.Controller.Entities
if (query.Recursive) if (query.Recursive)
{ {
query.Recursive = true; query.Recursive = true;
query.ParentId = parent.Id;
query.SetUser(user); query.SetUser(user);
if (query.IncludeItemTypes.Length == 0) 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 }; 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>(); var list = new List<BaseItem>();
@ -329,9 +332,13 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query) private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
{ {
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
.Where(i => !i.IsFolder) {
.OfType<IHasAlbumArtist>(); Recursive = true,
ParentId = parent.Id,
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
}).Cast<IHasAlbumArtist>();
var artists = _libraryManager.GetAlbumArtists(items); var artists = _libraryManager.GetAlbumArtists(items);
@ -340,9 +347,13 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query) private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
{ {
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
.Where(i => !i.IsFolder) {
.OfType<IHasArtist>(); Recursive = true,
ParentId = parent.Id,
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }
}).Cast<IHasArtist>();
var artists = _libraryManager.GetArtists(items); var artists = _libraryManager.GetArtists(items);
@ -351,9 +362,13 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query) private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
{ {
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
.Where(i => !i.IsFolder) {
.OfType<IHasAlbumArtist>(); 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); var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
@ -448,7 +463,6 @@ namespace MediaBrowser.Controller.Entities
if (query.Recursive) if (query.Recursive)
{ {
query.Recursive = true; query.Recursive = true;
query.ParentId = parent.Id;
query.SetUser(user); query.SetUser(user);
if (query.IncludeItemTypes.Length == 0) if (query.IncludeItemTypes.Length == 0)
@ -456,7 +470,7 @@ namespace MediaBrowser.Controller.Entities
query.IncludeItemTypes = new[] { typeof(Movie).Name, typeof(BoxSet).Name }; query.IncludeItemTypes = new[] { typeof(Movie).Name, typeof(BoxSet).Name };
} }
return _libraryManager.GetItemsResult(query); return parent.QueryRecursive(query);
} }
var list = new List<BaseItem>(); var list = new List<BaseItem>();
@ -613,7 +627,6 @@ namespace MediaBrowser.Controller.Entities
if (query.Recursive) if (query.Recursive)
{ {
query.Recursive = true; query.Recursive = true;
query.ParentId = parent.Id;
query.SetUser(user); query.SetUser(user);
if (query.IncludeItemTypes.Length == 0) 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 }; 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>(); var list = new List<BaseItem>();
@ -756,9 +769,9 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, queryParent, null, query, _libraryManager); 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, private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
@ -1121,22 +1134,6 @@ namespace MediaBrowser.Controller.Entities
bool? isVirtualUnaired, bool? isVirtualUnaired,
bool? isUnaired) 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) if (isMissing.HasValue)
{ {
var val = isMissing.Value; var val = isMissing.Value;
@ -1145,7 +1142,7 @@ namespace MediaBrowser.Controller.Entities
var e = i as Season; var e = i as Season;
if (e != null) if (e != null)
{ {
return (e.IsMissingSeason ?? false) == val; return (e.IsMissingSeason) == val;
} }
return true; return true;
}); });
@ -1277,11 +1274,6 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
if (query.Filter != null && !query.Filter(item))
{
return false;
}
UserItemData userData = null; UserItemData userData = null;
if (query.IsLiked.HasValue) if (query.IsLiked.HasValue)

View file

@ -63,13 +63,13 @@ namespace MediaBrowser.Controller.Playlists
return GetPlayableItems(user).Result; 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; 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; return items;
@ -129,7 +129,11 @@ namespace MediaBrowser.Controller.Playlists
var items = user == null var items = user == null
? LibraryManager.RootFolder.GetRecursiveChildren(filter) ? 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); return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
} }

View file

@ -401,10 +401,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
SortOrder = sort.SortOrder, SortOrder = sort.SortOrder,
User = user, User = user,
Recursive = true, Recursive = true,
Filter = FilterUnsupportedContent, IsMissing = false,
ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
IsFolder = isFolder, IsFolder = isFolder,
MediaTypes = mediaTypes.ToArray() MediaTypes = mediaTypes.ToArray()
}); });
} }
@ -461,8 +461,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
SortBy = sortOrders.ToArray(), SortBy = sortOrders.ToArray(),
SortOrder = sort.SortOrder, SortOrder = sort.SortOrder,
User = user, User = user,
Filter = FilterUnsupportedContent, IsMissing = false,
PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music } PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music },
ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
IsPlaceHolder = false
}).ConfigureAwait(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) private ServerItem GetItemFromObjectId(string id, User user)
{ {
return DidlBuilder.IsIdRoot(id) return DidlBuilder.IsIdRoot(id)

View file

@ -215,6 +215,9 @@ namespace MediaBrowser.Model.Configuration
{ {
Migrations = new string[] { }; Migrations = new string[] { };
EnableLocalizedGuids = true;
EnableCustomPathSubFolders = true;
ImageSavingConvention = ImageSavingConvention.Compatible; ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096; PublicPort = 8096;
PublicHttpsPort = 8920; PublicHttpsPort = 8920;

View file

@ -1,8 +1,8 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Extensions;
using System.Diagnostics; using System.Diagnostics;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Entities namespace MediaBrowser.Model.Entities
{ {
@ -53,18 +53,22 @@ namespace MediaBrowser.Model.Entities
if (!string.IsNullOrEmpty(Language)) if (!string.IsNullOrEmpty(Language))
{ {
attributes.Add(Language); attributes.Add(StringHelper.FirstToUpper(Language));
} }
if (!string.IsNullOrEmpty(Codec) && !StringHelper.EqualsIgnoreCase(Codec, "dca")) if (!string.IsNullOrEmpty(Codec) && !StringHelper.EqualsIgnoreCase(Codec, "dca"))
{ {
attributes.Add(Codec); attributes.Add(AudioCodec.GetFriendlyName(Codec));
} }
if (!string.IsNullOrEmpty(Profile) && !StringHelper.EqualsIgnoreCase(Profile, "lc")) else if (!string.IsNullOrEmpty(Profile) && !StringHelper.EqualsIgnoreCase(Profile, "lc"))
{ {
attributes.Add(Profile); attributes.Add(Profile);
} }
if (Channels.HasValue) if (!string.IsNullOrEmpty(ChannelLayout))
{
attributes.Add(ChannelLayout);
}
else if (Channels.HasValue)
{ {
attributes.Add(StringHelper.ToStringCultureInvariant(Channels.Value) + " ch"); attributes.Add(StringHelper.ToStringCultureInvariant(Channels.Value) + " ch");
} }

View file

@ -125,5 +125,10 @@ namespace MediaBrowser.Model.Extensions
return sb.ToString(); return sb.ToString();
} }
public static string FirstToUpper(this string str)
{
return string.IsNullOrEmpty(str) ? "" : str.Substring(0, 1).ToUpper() + str.Substring(1);
}
} }
} }

View file

@ -20,12 +20,15 @@ namespace MediaBrowser.Model.LiveTv
public int PrePaddingSeconds { get; set; } public int PrePaddingSeconds { get; set; }
public int PostPaddingSeconds { get; set; } public int PostPaddingSeconds { get; set; }
public string[] MediaLocationsCreated { get; set; }
public LiveTvOptions() public LiveTvOptions()
{ {
EnableMovieProviders = true; EnableMovieProviders = true;
EnableRecordingSubfolders = true; EnableRecordingSubfolders = true;
TunerHosts = new List<TunerHostInfo>(); TunerHosts = new List<TunerHostInfo>();
ListingProviders = new List<ListingsProviderInfo>(); ListingProviders = new List<ListingsProviderInfo>();
MediaLocationsCreated = new string[] { };
} }
} }

View file

@ -5,5 +5,22 @@
public const string AAC = "aac"; public const string AAC = "aac";
public const string MP3 = "mp3"; public const string MP3 = "mp3";
public const string AC3 = "ac3"; 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();
}
}
} }
} }

View file

@ -288,6 +288,8 @@ namespace MediaBrowser.Model.Querying
[Obsolete] [Obsolete]
public string Person { get; set; } public string Person { get; set; }
public bool EnableTotalRecordCount { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ItemQuery" /> class. /// Initializes a new instance of the <see cref="ItemQuery" /> class.
/// </summary> /// </summary>
@ -306,6 +308,8 @@ namespace MediaBrowser.Model.Querying
VideoTypes = new VideoType[] { }; VideoTypes = new VideoType[] { };
EnableTotalRecordCount = true;
Artists = new string[] { }; Artists = new string[] { };
Studios = new string[] { }; Studios = new string[] { };

View file

@ -145,11 +145,15 @@ namespace MediaBrowser.Providers.Manager
bool hasRefreshedMetadata = true; bool hasRefreshedMetadata = true;
bool hasRefreshedImages = true; bool hasRefreshedImages = true;
var requiresRefresh = false;
// Next run metadata providers // Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) 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(); .ToList();
var dateLastRefresh = EnableDateLastRefreshed(item) var dateLastRefresh = EnableDateLastRefreshed(item)
@ -217,11 +221,11 @@ namespace MediaBrowser.Providers.Manager
var isFirstRefresh = GetLastRefreshDate(item) == default(DateTime); 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; updateType = updateType | beforeSaveResult;
// Save if changes were made, or it's never been saved before // 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 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) if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata)
@ -461,11 +465,8 @@ namespace MediaBrowser.Providers.Manager
/// <summary> /// <summary>
/// Gets the providers. /// Gets the providers.
/// </summary> /// </summary>
/// <param name="item">The item.</param>
/// <param name="status">The status.</param>
/// <param name="options">The options.</param>
/// <returns>IEnumerable{`0}.</returns> /// <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 // Get providers to refresh
var providers = ((ProviderManager)ProviderManager).GetMetadataProviders<TItemType>(item).ToList(); var providers = ((ProviderManager)ProviderManager).GetMetadataProviders<TItemType>(item).ToList();
@ -475,7 +476,7 @@ namespace MediaBrowser.Providers.Manager
: status.DateLastMetadataRefresh ?? default(DateTime); : status.DateLastMetadataRefresh ?? default(DateTime);
// Run all if either of these flags are true // 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) if (!runAllProviders)
{ {
@ -668,12 +669,6 @@ namespace MediaBrowser.Providers.Manager
// If a local provider fails, consider that a failure // If a local provider fails, consider that a failure
refreshResult.ErrorMessage = ex.Message; 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;
}
} }
} }

View file

@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.TV
if (!hasSeason) if (!hasSeason)
{ {
await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); await AddSeason(series, seasonNumber, false, cancellationToken).ConfigureAwait(false);
hasChanges = true; hasChanges = true;
} }
@ -83,7 +83,7 @@ namespace MediaBrowser.Providers.TV
if (!hasSeason) if (!hasSeason)
{ {
await AddSeason(series, null, cancellationToken).ConfigureAwait(false); await AddSeason(series, null, false, cancellationToken).ConfigureAwait(false);
hasChanges = true; hasChanges = true;
} }
@ -95,12 +95,9 @@ namespace MediaBrowser.Providers.TV
/// <summary> /// <summary>
/// Adds the season. /// Adds the season.
/// </summary> /// </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, public async Task<Season> AddSeason(Series series,
int? seasonNumber, int? seasonNumber,
bool isVirtualItem,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var seasonName = seasonNumber == 0 ? var seasonName = seasonNumber == 0 ?
@ -113,7 +110,8 @@ namespace MediaBrowser.Providers.TV
{ {
Name = seasonName, Name = seasonName,
IndexNumber = seasonNumber, 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); season.SetParent(series);

View file

@ -418,7 +418,7 @@ namespace MediaBrowser.Providers.TV
if (season == null) if (season == null)
{ {
var provider = new DummySeasonProvider(_config, _logger, _localization, _libraryManager, _fileSystem); 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)); var name = string.Format("Episode {0}", episodeNumber.ToString(_usCulture));

View file

@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.TV
{ {
var episodes = item.GetEpisodes().ToList(); var episodes = item.GetEpisodes().ToList();
updateType |= SavePremiereDate(item, episodes); updateType |= SavePremiereDate(item, episodes);
updateType |= SaveIsMissing(item, episodes); updateType |= SaveIsVirtualItem(item, episodes);
} }
return updateType; return updateType;
@ -67,13 +67,13 @@ namespace MediaBrowser.Providers.TV
return ItemUpdateType.None; 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; return ItemUpdateType.MetadataEdit;
} }

View file

@ -1448,8 +1448,12 @@ namespace MediaBrowser.Server.Implementations.Library
// Handle grouping // Handle grouping
if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType)) 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 user.RootFolder
return collectionFolders.SelectMany(i => GetTopParentsForQuery(i, user)); .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[] { }; return new BaseItem[] { };
} }

View file

@ -30,7 +30,10 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user) public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user)
{ {
var genres = user.RootFolder var genres = user.RootFolder
.GetRecursiveChildren(user, i => i is Audio) .GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>() .Cast<Audio>()
.Where(i => i.HasAnyArtist(artist.Name)) .Where(i => i.HasAnyArtist(artist.Name))
.SelectMany(i => i.Genres) .SelectMany(i => i.Genres)
@ -43,7 +46,10 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user) public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
{ {
var genres = item var genres = item
.GetRecursiveChildren(user, i => i is Audio) .GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>() .Cast<Audio>()
.SelectMany(i => i.Genres) .SelectMany(i => i.Genres)
.Concat(item.Genres) .Concat(item.Genres)
@ -55,7 +61,10 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user) public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
{ {
var genres = item var genres = item
.GetRecursiveChildren(user, i => i is Audio) .GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] {typeof(Audio).Name}
})
.Cast<Audio>() .Cast<Audio>()
.SelectMany(i => i.Genres) .SelectMany(i => i.Genres)
.Concat(item.Genres) .Concat(item.Genres)
@ -67,7 +76,10 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user) public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
{ {
var genres = item var genres = item
.GetRecursiveChildren(user, i => i is Audio) .GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>() .Cast<Audio>()
.SelectMany(i => i.Genres) .SelectMany(i => i.Genres)
.Concat(item.Genres) .Concat(item.Genres)

View file

@ -115,17 +115,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{ {
var recordingFolders = GetRecordingFolders(); var recordingFolders = GetRecordingFolders();
var defaultRecordingPath = DefaultRecordingPath;
if (!recordingFolders.Any(i => i.Locations.Contains(defaultRecordingPath, StringComparer.OrdinalIgnoreCase)))
{
RemovePathFromLibrary(defaultRecordingPath);
}
var virtualFolders = _libraryManager.GetVirtualFolders() var virtualFolders = _libraryManager.GetVirtualFolders()
.ToList(); .ToList();
var allExistingPaths = virtualFolders.SelectMany(i => i.Locations).ToList(); var allExistingPaths = virtualFolders.SelectMany(i => i.Locations).ToList();
var pathsAdded = new List<string>();
foreach (var recordingFolder in recordingFolders) foreach (var recordingFolder in recordingFolders)
{ {
var pathsToCreate = recordingFolder.Locations var pathsToCreate = recordingFolder.Locations
@ -145,11 +141,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{ {
_logger.ErrorException("Error creating virtual folder", ex); _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) private void RemovePathFromLibrary(string path)
{ {
_logger.Debug("Removing path from library: {0}", path);
var requiresRefresh = false; var requiresRefresh = false;
var virtualFolders = _libraryManager.GetVirtualFolders() var virtualFolders = _libraryManager.GetVirtualFolders()
.ToList(); .ToList();

View file

@ -527,6 +527,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, Guid parentFolderId, CancellationToken cancellationToken) private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, Guid parentFolderId, CancellationToken cancellationToken)
{ {
var isNew = false; var isNew = false;
var forceUpdate = false;
var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id); var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id);
@ -576,10 +577,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath)) if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath))
{ {
item.SetImagePath(ImageType.Primary, channelInfo.ImagePath); item.SetImagePath(ImageType.Primary, channelInfo.ImagePath);
forceUpdate = true;
} }
else if (!string.IsNullOrWhiteSpace(channelInfo.ImageUrl)) else if (!string.IsNullOrWhiteSpace(channelInfo.ImageUrl))
{ {
item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl); item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl);
forceUpdate = true;
} }
} }
@ -588,9 +591,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
item.Name = channelInfo.Name; 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) await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
{ {
ForceSave = isNew ForceSave = isNew || forceUpdate
}, cancellationToken); }, cancellationToken);
@ -1398,16 +1410,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.Where(i => i.IsVisibleStandalone(user)) .Where(i => i.IsVisibleStandalone(user))
.ToList(); .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 }, MediaTypes = new[] { MediaType.Video },
Recursive = true, Recursive = true,
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
IsFolder = false,
ExcludeLocationTypes = new[] { LocationType.Virtual }, 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) public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)

View file

@ -55,9 +55,9 @@
<Reference Include="Interfaces.IO"> <Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath> <HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference> </Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.5917.1514, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="MediaBrowser.Naming, Version=1.0.5981.21615, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\MediaBrowser.Naming.1.0.0.50\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.49\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> <Private>True</Private>
</Reference> </Reference>
<Reference Include="MoreLinq"> <Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath> <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
@ -68,8 +68,8 @@
<Reference Include="ServiceStack.Api.Swagger"> <Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference> </Reference>
<Reference Include="SimpleInjector, Version=3.1.3.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll</HintPath> <HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SocketHttpListener, Version=1.0.5955.1537, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SocketHttpListener, Version=1.0.5955.1537, Culture=neutral, processorArchitecture=MSIL">

View file

@ -81,10 +81,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deleteUserDataKeysCommand; private IDbCommand _deleteUserDataKeysCommand;
private IDbCommand _saveUserDataKeysCommand; private IDbCommand _saveUserDataKeysCommand;
private IDbCommand _deleteItemValuesCommand;
private IDbCommand _saveItemValuesCommand;
private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedRatingCommand;
private IDbCommand _updateInheritedTagsCommand; private IDbCommand _updateInheritedTagsCommand;
public const int LatestSchemaVersion = 78; public const int LatestSchemaVersion = 79;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class. /// 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 table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT, PRIMARY KEY (ItemId, UserDataKey))",
"create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)", "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 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 idxPeopleItemId on People(ItemId)",
"create index if not exists idxPeopleName on People(Name)", "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", "PrimaryVersionId", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME");
_connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT");
_connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT");
@ -353,7 +360,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"DateLastMediaAdded", "DateLastMediaAdded",
"Album", "Album",
"CriticRating", "CriticRating",
"CriticRatingSummary" "CriticRatingSummary",
"IsVirtualItem"
}; };
private readonly string[] _mediaStreamSaveColumns = private readonly string[] _mediaStreamSaveColumns =
@ -468,7 +476,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"OriginalTitle", "OriginalTitle",
"PrimaryVersionId", "PrimaryVersionId",
"DateLastMediaAdded", "DateLastMediaAdded",
"Album" "Album",
"IsVirtualItem"
}; };
_saveItemCommand = _connection.CreateCommand(); _saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; _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, "@UserDataKey");
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority"); _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> /// <summary>
@ -722,7 +742,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; _saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed;
} }
if (item.DateLastSaved == default(DateTime))
{
_saveItemCommand.GetParameter(index++).Value = null;
}
else
{
_saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved;
}
_saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; _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.LockedFields.Select(i => i.ToString()).ToArray());
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.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; _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.Transaction = transaction;
_saveItemCommand.ExecuteNonQuery(); _saveItemCommand.ExecuteNonQuery();
@ -851,6 +889,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
} }
UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction);
UpdateItemValues(item.Id, GetItemValues(item), transaction);
} }
transaction.Commit(); transaction.Commit();
@ -1255,6 +1294,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
item.CriticRatingSummary = reader.GetString(57); item.CriticRatingSummary = reader.GetString(57);
} }
var season = item as Season;
if (season != null && !reader.IsDBNull(58))
{
season.IsVirtualItem = reader.GetBoolean(58);
}
return item; return item;
} }
@ -1661,7 +1706,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{ {
var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds;
if (elapsed >= 500) if (elapsed >= 400)
{ {
Logger.Debug("{2} query time (slow): {0}ms. Query: {1}", Logger.Debug("{2} query time (slow): {0}ms. Query: {1}",
Convert.ToInt32(elapsed), Convert.ToInt32(elapsed),
@ -1795,7 +1840,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}).ToArray()); }).ToArray());
} }
private Tuple<string,bool> MapOrderByField(string name) private Tuple<string, bool> MapOrderByField(string name)
{ {
if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
{ {
@ -1838,6 +1883,14 @@ namespace MediaBrowser.Server.Implementations.Persistence
{ {
return new Tuple<string, bool>("DateLastMediaAdded", false); 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); return new Tuple<string, bool>(name, false);
} }
@ -2405,6 +2458,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@IsFavorite", DbType.Boolean).Value = query.IsFavorite.Value; cmd.Parameters.Add(cmd, "@IsFavorite", DbType.Boolean).Value = query.IsFavorite.Value;
} }
if (EnableJoinUserData(query))
{
if (query.IsPlayed.HasValue) if (query.IsPlayed.HasValue)
{ {
if (query.IsPlayed.Value) if (query.IsPlayed.Value)
@ -2417,6 +2472,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
} }
cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value; cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value;
} }
}
if (query.IsResumable.HasValue) 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) if (query.Genres.Length > 0)
{ {
var clauses = new List<string>(); var clauses = new List<string>();
@ -2967,6 +3037,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteUserDataKeysCommand.Transaction = transaction; _deleteUserDataKeysCommand.Transaction = transaction;
_deleteUserDataKeysCommand.ExecuteNonQuery(); _deleteUserDataKeysCommand.ExecuteNonQuery();
// Delete item values
_deleteItemValuesCommand.GetParameter(0).Value = id;
_deleteItemValuesCommand.Transaction = transaction;
_deleteItemValuesCommand.ExecuteNonQuery();
// Delete the item // Delete the item
_deleteItemCommand.GetParameter(0).Value = id; _deleteItemCommand.GetParameter(0).Value = id;
_deleteItemCommand.Transaction = transaction; _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) private void UpdateUserDataKeys(Guid itemId, List<string> keys, IDbTransaction transaction)
{ {
if (itemId == Guid.Empty) if (itemId == Guid.Empty)

View file

@ -4,10 +4,10 @@
<package id="Emby.XmlTv" version="1.0.0.48" targetFramework="net45" /> <package id="Emby.XmlTv" version="1.0.0.48" targetFramework="net45" />
<package id="ini-parser" version="2.2.4" 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="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="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
<package id="morelinq" version="1.4.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="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" /> <package id="SocketHttpListener" version="1.0.0.30" targetFramework="net45" />
</packages> </packages>

View file

@ -107,9 +107,6 @@
<Content Include="dashboard-ui\components\chromecasthelpers.js"> <Content Include="dashboard-ui\components\chromecasthelpers.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\bower_components\fastclick\lib\fastclick.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\components\favoriteitems.js"> <Content Include="dashboard-ui\components\favoriteitems.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -1686,6 +1683,9 @@
<None Include="dashboard-ui\strings\id.json"> <None Include="dashboard-ui\strings\id.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="dashboard-ui\strings\sk.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\strings\zh-HK.json"> <None Include="dashboard-ui\strings\zh-HK.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common.Internal</id> <id>MediaBrowser.Common.Internal</id>
<version>3.0.647</version> <version>3.0.648</version>
<title>MediaBrowser.Common.Internal</title> <title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors> <authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners> <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> <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.647" /> <dependency id="MediaBrowser.Common" version="3.0.648" />
<dependency id="NLog" version="4.3.1" /> <dependency id="NLog" version="4.3.4" />
<dependency id="SimpleInjector" version="3.1.3" /> <dependency id="SimpleInjector" version="3.1.4" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.647</version> <version>3.0.648</version>
<title>MediaBrowser.Common</title> <title>MediaBrowser.Common</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View file

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

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.647</version> <version>3.0.648</version>
<title>Media Browser.Server.Core</title> <title>Media Browser.Server.Core</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description> <description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <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" /> <dependency id="Interfaces.IO" version="1.0.0.5" />
</dependencies> </dependencies>
</metadata> </metadata>