diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-07-05 09:47:10 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-07-05 09:47:10 -0400 |
| commit | a19bfc8f07790c9108e09606b590b78fbcb512e6 (patch) | |
| tree | 2545c89e7f9ec59fc854097cea543678c664f20d | |
| parent | f98b611debd757dcf2b2862fa04f28d514a7fa3d (diff) | |
Added support for linked children
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/ItemsService.cs | 4 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Dto/DtoBuilder.cs | 15 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/BaseItem.cs | 30 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/Folder.cs | 116 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/LinkedChild.cs | 38 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 8 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaBrowser.Controller.csproj | 1 | ||||
| -rw-r--r-- | MediaBrowser.Model/Dto/ImageOptions.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.ServerApplication/App.xaml.cs | 9 | ||||
| -rw-r--r-- | MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs | 12 |
12 files changed, 194 insertions, 44 deletions
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index b93d339ce..df728ee0d 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Api.UserLibrary if (request.UserId.HasValue) { - items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user); + items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user, true); } else { diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 10e56af52..8497901f6 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -305,7 +305,7 @@ namespace MediaBrowser.Api.UserLibrary return ((Folder)item).GetRecursiveChildren(user); } - return ((Folder)item).GetChildren(user, request.IndexBy); + return ((Folder)item).GetChildren(user, true, request.IndexBy); } /// <summary> @@ -433,7 +433,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = DtoBuilder.GetItemByClientId(request.AdjacentTo, _userManager, _libraryManager); - var allSiblings = item.Parent.GetChildren(user).OrderBy(i => i.SortName).ToList(); + var allSiblings = item.Parent.GetChildren(user, true).OrderBy(i => i.SortName).ToList(); var index = allSiblings.IndexOf(item); diff --git a/MediaBrowser.Controller/Dto/DtoBuilder.cs b/MediaBrowser.Controller/Dto/DtoBuilder.cs index b321df2d1..b921566aa 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 320225031..1cbe5b635 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 c6d6bf221..297d513e5 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 000000000..edc5a7ac8 --- /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 34f09b4b0..2ee3ccffe 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 502c7a7b8..6910722d6 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" /> diff --git a/MediaBrowser.Model/Dto/ImageOptions.cs b/MediaBrowser.Model/Dto/ImageOptions.cs index 80614831a..63c0f70ab 100644 --- a/MediaBrowser.Model/Dto/ImageOptions.cs +++ b/MediaBrowser.Model/Dto/ImageOptions.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Model.Dto public ImageOptions() { Quality = 100; + EnableImageEnhancers = true; } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 71d014468..02ecb4fca 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -229,7 +229,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { var user = _userManager.GetUserById(userId); - var collections = user.RootFolder.GetChildren(user).ToList(); + var collections = user.RootFolder.GetChildren(user, true).ToList(); var allRecursiveChildren = user.RootFolder.GetRecursiveChildren(user).ToDictionary(i => i.Id); diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index 5ed253763..db923e5e2 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -255,7 +255,14 @@ namespace MediaBrowser.ServerApplication process.Exited += ProcessExited; - process.Start(); + try + { + process.Start(); + } + catch (Exception ex) + { + MessageBox.Show("There was an error launching your web browser. Please check your defualt browser settings."); + } } /// <summary> diff --git a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs index 577ac93bb..6dabd85af 100644 --- a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs +++ b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.ServerApplication Cursor = Cursors.Wait; await Task.Run(() => { - IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser); + IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser, true); children = OrderByName(children, CurrentUser); foreach (Folder folder in children) @@ -102,7 +102,7 @@ namespace MediaBrowser.ServerApplication var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id)) ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName }; var node = new TreeViewItem { Tag = currentFolder }; - var subChildren = currentFolder.GetChildren(CurrentUser, prefs.IndexBy); + var subChildren = currentFolder.GetChildren(CurrentUser, true, prefs.IndexBy); subChildren = OrderByName(subChildren, CurrentUser); AddChildren(node, subChildren, CurrentUser); node.Header = currentFolder.Name + " (" + @@ -153,8 +153,8 @@ namespace MediaBrowser.ServerApplication if (subFolder != null) { var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.GetDisplayPreferencesId(user.Id)); - - AddChildren(node, OrderBy(subFolder.GetChildren(user), user, prefs.SortBy), user); + + AddChildren(node, OrderBy(subFolder.GetChildren(user, true), user, prefs.SortBy), user); node.Header = item.Name + " (" + node.Items.Count + ")"; } else @@ -374,7 +374,7 @@ namespace MediaBrowser.ServerApplication //re-build the current item's children as an index prefs.IndexBy = ddlIndexBy.SelectedItem as string; treeItem.Items.Clear(); - AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser); + AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser); treeItem.Header = folder.Name + "(" + treeItem.Items.Count + ")"; Cursor = Cursors.Arrow; @@ -415,7 +415,7 @@ namespace MediaBrowser.ServerApplication //re-sort prefs.SortBy = ddlSortBy.SelectedItem as string; treeItem.Items.Clear(); - AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser); + AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser); treeItem.Header = folder.Name + "(" + treeItem.Items.Count + ")"; Cursor = Cursors.Arrow; |
