aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2013-07-05 09:47:10 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2013-07-05 09:47:10 -0400
commita19bfc8f07790c9108e09606b590b78fbcb512e6 (patch)
tree2545c89e7f9ec59fc854097cea543678c664f20d /MediaBrowser.Controller
parentf98b611debd757dcf2b2862fa04f28d514a7fa3d (diff)
Added support for linked children
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Dto/DtoBuilder.cs15
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs30
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs116
-rw-r--r--MediaBrowser.Controller/Entities/LinkedChild.cs38
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs8
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
6 files changed, 175 insertions, 33 deletions
diff --git a/MediaBrowser.Controller/Dto/DtoBuilder.cs b/MediaBrowser.Controller/Dto/DtoBuilder.cs
index b321df2d18..b921566aa6 100644
--- a/MediaBrowser.Controller/Dto/DtoBuilder.cs
+++ b/MediaBrowser.Controller/Dto/DtoBuilder.cs
@@ -127,7 +127,7 @@ namespace MediaBrowser.Controller.Dto
var folder = (Folder)item;
// Skip sorting since all we want is a count
- dto.ChildCount = folder.GetChildren(user).Count();
+ dto.ChildCount = folder.GetChildren(user, true).Count();
SetSpecialCounts(folder, user, dto, _userDataRepository);
}
@@ -555,7 +555,7 @@ namespace MediaBrowser.Controller.Dto
double totalPercentPlayed = 0;
// Loop through each recursive child
- foreach (var child in folder.GetRecursiveChildren(user).Where(i => !i.IsFolder).ToList())
+ foreach (var child in folder.GetRecursiveChildren(user, true).Where(i => !i.IsFolder).ToList())
{
var userdata = userDataRepository.GetUserData(user.Id, child.GetUserDataKey());
@@ -610,11 +610,6 @@ namespace MediaBrowser.Controller.Dto
/// <returns>Task.</returns>
private async Task AttachPeople(BaseItemDto dto, BaseItem item)
{
- if (item.People == null)
- {
- return;
- }
-
// Ordering by person type to ensure actors and artists are at the front.
// This is taking advantage of the fact that they both begin with A
// This should be improved in the future
@@ -640,7 +635,7 @@ namespace MediaBrowser.Controller.Dto
)).ConfigureAwait(false);
- var dictionary = entities.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
+ var dictionary = entities.Where(i => i != null).ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < people.Count; i++)
{
@@ -698,7 +693,7 @@ namespace MediaBrowser.Controller.Dto
)).ConfigureAwait(false);
- var dictionary = entities.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
+ var dictionary = entities.Where(i => i != null).ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < studios.Count; i++)
{
@@ -967,7 +962,7 @@ namespace MediaBrowser.Controller.Dto
values.RemoveRange(0, 2);
// Get the IndexFolder
- var indexFolder = parentFolder.GetChildren(user, indexBy).FirstOrDefault(i => i.Id == indexFolderId) as Folder;
+ var indexFolder = parentFolder.GetChildren(user, false, indexBy).FirstOrDefault(i => i.Id == indexFolderId) as Folder;
// Nested index folder
if (values.Count > 0)
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 3202250314..1cbe5b635c 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -617,6 +617,11 @@ namespace MediaBrowser.Controller.Entities
try
{
resolveArgs = ResolveArgs;
+
+ if (!resolveArgs.IsDirectory)
+ {
+ return new List<Trailer>();
+ }
}
catch (IOException ex)
{
@@ -624,11 +629,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Trailer>();
}
- if (!resolveArgs.IsDirectory)
- {
- return new List<Trailer>();
- }
-
var files = new List<FileSystemInfo>();
var folder = resolveArgs.GetFileSystemEntryByName(TrailerFolderName);
@@ -687,6 +687,11 @@ namespace MediaBrowser.Controller.Entities
try
{
resolveArgs = ResolveArgs;
+
+ if (!resolveArgs.IsDirectory)
+ {
+ return new List<Audio.Audio>();
+ }
}
catch (IOException ex)
{
@@ -694,11 +699,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Audio.Audio>();
}
- if (!resolveArgs.IsDirectory)
- {
- return new List<Audio.Audio>();
- }
-
var files = new List<FileSystemInfo>();
var folder = resolveArgs.GetFileSystemEntryByName(ThemeSongsFolderName);
@@ -747,6 +747,11 @@ namespace MediaBrowser.Controller.Entities
try
{
resolveArgs = ResolveArgs;
+
+ if (!resolveArgs.IsDirectory)
+ {
+ return new List<Video>();
+ }
}
catch (IOException ex)
{
@@ -754,11 +759,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Video>();
}
- if (!resolveArgs.IsDirectory)
- {
- return new List<Video>();
- }
-
var folder = resolveArgs.GetFileSystemEntryByName(ThemeVideosFolderName);
// Path doesn't exist. No biggie
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index c6d6bf2210..297d513e5b 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence;
@@ -21,6 +22,11 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Folder : BaseItem
{
+ public Folder()
+ {
+ LinkedChildren = new List<LinkedChild>();
+ }
+
/// <summary>
/// Gets a value indicating whether this instance is folder.
/// </summary>
@@ -83,6 +89,13 @@ namespace MediaBrowser.Controller.Entities
return (userId + DisplayPreferencesId.ToString()).GetMD5();
}
+ public List<LinkedChild> LinkedChildren { get; set; }
+
+ protected virtual bool SupportsLinkedChildren
+ {
+ get { return false; }
+ }
+
/// <summary>
/// Adds the child.
/// </summary>
@@ -878,10 +891,11 @@ namespace MediaBrowser.Controller.Entities
/// Gets allowed children of an item
/// </summary>
/// <param name="user">The user.</param>
+ /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <param name="indexBy">The index by.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- public virtual IEnumerable<BaseItem> GetChildren(User user, string indexBy = null)
+ public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null)
{
if (user == null)
{
@@ -889,7 +903,7 @@ namespace MediaBrowser.Controller.Entities
}
//the true root should return our users root folder children
- if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, indexBy);
+ if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren, indexBy);
IEnumerable<BaseItem> result = null;
@@ -898,24 +912,37 @@ namespace MediaBrowser.Controller.Entities
result = GetIndexedChildren(user, indexBy);
}
+ if (result != null)
+ {
+ return result;
+ }
+
+ var children = Children;
+
+ if (includeLinkedChildren)
+ {
+ children = children.Concat(GetLinkedChildren());
+ }
+
// If indexed is false or the indexing function is null
- return result ?? (Children.Where(c => c.IsVisible(user)));
+ return children.Where(c => c.IsVisible(user));
}
/// <summary>
/// Gets allowed recursive children of an item
/// </summary>
/// <param name="user">The user.</param>
+ /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- public IEnumerable<BaseItem> GetRecursiveChildren(User user)
+ public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = false)
{
if (user == null)
{
throw new ArgumentNullException();
}
- foreach (var item in GetChildren(user))
+ foreach (var item in GetChildren(user, includeLinkedChildren))
{
yield return item;
@@ -923,7 +950,7 @@ namespace MediaBrowser.Controller.Entities
if (subFolder != null)
{
- foreach (var subitem in subFolder.GetRecursiveChildren(user))
+ foreach (var subitem in subFolder.GetRecursiveChildren(user, includeLinkedChildren))
{
yield return subitem;
}
@@ -932,6 +959,81 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Gets the linked children.
+ /// </summary>
+ /// <returns>IEnumerable{BaseItem}.</returns>
+ public IEnumerable<BaseItem> GetLinkedChildren()
+ {
+ return LinkedChildren
+ .Select(i => LibraryManager.RootFolder.FindByPath(i.Path))
+ .Where(i => i != null);
+ }
+
+ public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ {
+ var changed = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
+
+ return changed || (SupportsLinkedChildren && RefreshLinkedChildren());
+ }
+
+ /// <summary>
+ /// Refreshes the linked children.
+ /// </summary>
+ /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
+ private bool RefreshLinkedChildren()
+ {
+ ItemResolveArgs resolveArgs;
+
+ try
+ {
+ resolveArgs = ResolveArgs;
+
+ if (!resolveArgs.IsDirectory)
+ {
+ return false;
+ }
+ }
+ catch (IOException ex)
+ {
+ Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
+ return false;
+ }
+
+ var currentManualLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Manual).ToList();
+ var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList();
+
+ var newShortcutLinks = resolveArgs.FileSystemChildren
+ .Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory && FileSystem.IsShortcut(i.FullName))
+ .Select(i =>
+ {
+ try
+ {
+ return new LinkedChild
+ {
+ Path = FileSystem.ResolveShortcut(i.FullName),
+ Type = LinkedChildType.Shortcut
+ };
+ }
+ catch (IOException ex)
+ {
+ Logger.ErrorException("Error resolving shortcut {0}", ex, i.FullName);
+ return null;
+ }
+ })
+ .Where(i => i != null)
+ .ToList();
+
+ if (!newShortcutLinks.SequenceEqual(currentShortcutLinks))
+ {
+ newShortcutLinks.AddRange(currentManualLinks);
+ LinkedChildren = newShortcutLinks;
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
/// Folders need to validate and refresh
/// </summary>
/// <returns>Task.</returns>
@@ -954,7 +1056,7 @@ namespace MediaBrowser.Controller.Entities
public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager)
{
// Sweep through recursively and update status
- var tasks = GetRecursiveChildren(user).Where(i => !i.IsFolder).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager));
+ var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager));
await Task.WhenAll(tasks).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs
new file mode 100644
index 0000000000..edc5a7ac88
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/LinkedChild.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+
+namespace MediaBrowser.Controller.Entities
+{
+ public class LinkedChild
+ {
+ public string Path { get; set; }
+ public LinkedChildType Type { get; set; }
+ }
+
+ public enum LinkedChildType
+ {
+ Manual = 1,
+ Shortcut = 2
+ }
+
+ public class LinkedChildComparer : IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ var a = (LinkedChild)x;
+
+ var b = (LinkedChild)y;
+
+ if (!string.Equals(a.Path, b.Path, StringComparison.OrdinalIgnoreCase))
+ {
+ return string.Compare(a.Path, b.Path, StringComparison.OrdinalIgnoreCase);
+ }
+ if (a.Type != b.Type)
+ {
+ return a.Type.CompareTo(b.Type);
+ }
+
+ return 0;
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 34f09b4b09..2ee3ccffe9 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -6,6 +6,12 @@ namespace MediaBrowser.Controller.Entities.Movies
/// </summary>
public class BoxSet : Folder
{
-
+ protected override bool SupportsLinkedChildren
+ {
+ get
+ {
+ return true;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 502c7a7b82..6910722d68 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -78,6 +78,7 @@
<Compile Include="Entities\GameGenre.cs" />
<Compile Include="Entities\IByReferenceItem.cs" />
<Compile Include="Entities\IItemByName.cs" />
+ <Compile Include="Entities\LinkedChild.cs" />
<Compile Include="Entities\MusicVideo.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
<Compile Include="Library\ILibraryPrescanTask.cs" />