mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-31 00:01:12 +01:00 
			
		
		
		
	Merge with default
This commit is contained in:
		
						commit
						f385fe2f20
					
				| @ -288,7 +288,7 @@ namespace MediaBrowser.Api | |||||||
| 
 | 
 | ||||||
|             if (folder != null) |             if (folder != null) | ||||||
|             { |             { | ||||||
|                 IEnumerable<BaseItem> children = folder.GetParentalAllowedChildren(user); |                 IEnumerable<BaseItem> children = folder.GetChildren(user); | ||||||
| 
 | 
 | ||||||
|                 dto.Children = await Task.WhenAll(children.Select(c => GetDtoBaseItem(c, user, false, false))).ConfigureAwait(false); |                 dto.Children = await Task.WhenAll(children.Select(c => GetDtoBaseItem(c, user, false, false))).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             int count = 0; |             int count = 0; | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             var data = new Dictionary<string, int>(); |             var data = new Dictionary<string, int>(); | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             int count = 0; |             int count = 0; | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             int count = 0; |             int count = 0; | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             var data = new Dictionary<string, int>(); |             var data = new Dictionary<string, int>(); | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             int count = 0; |             int count = 0; | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ namespace MediaBrowser.Api.HttpHandlers | |||||||
|             var data = new Dictionary<int, int>(); |             var data = new Dictionary<int, int>(); | ||||||
| 
 | 
 | ||||||
|             // Get all the allowed recursive children |             // Get all the allowed recursive children | ||||||
|             IEnumerable<BaseItem> allItems = parent.GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> allItems = parent.GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             foreach (var item in allItems) |             foreach (var item in allItems) | ||||||
|             { |             { | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								MediaBrowser.Common/Extensions/BaseExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								MediaBrowser.Common/Extensions/BaseExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using System.Security.Cryptography; | ||||||
|  | 
 | ||||||
|  | namespace MediaBrowser.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class BaseExtensions | ||||||
|  |     { | ||||||
|  |         static MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider(); | ||||||
|  | 
 | ||||||
|  |         public static Guid GetMD5(this string str) | ||||||
|  |         { | ||||||
|  |             lock (md5Provider) | ||||||
|  |             { | ||||||
|  |                 return new Guid(md5Provider.ComputeHash(Encoding.Unicode.GetBytes(str))); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static bool ContainsStartsWith(this List<string> lst, string value) | ||||||
|  |         { | ||||||
|  |             foreach (var str in lst) | ||||||
|  |             { | ||||||
|  |                 if (str.StartsWith(value, StringComparison.OrdinalIgnoreCase)) return true; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -81,6 +81,7 @@ | |||||||
|     <Reference Include="WindowsBase" /> |     <Reference Include="WindowsBase" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <Compile Include="Extensions\BaseExtensions.cs" /> | ||||||
|     <Compile Include="Kernel\BaseApplicationPaths.cs" /> |     <Compile Include="Kernel\BaseApplicationPaths.cs" /> | ||||||
|     <Compile Include="Drawing\DrawingUtils.cs" /> |     <Compile Include="Drawing\DrawingUtils.cs" /> | ||||||
|     <Compile Include="Logging\TraceLogger.cs" /> |     <Compile Include="Logging\TraceLogger.cs" /> | ||||||
|  | |||||||
| @ -1,4 +1,8 @@ | |||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using MediaBrowser.Controller.Library; | ||||||
|  | using MediaBrowser.Controller.IO; | ||||||
| 
 | 
 | ||||||
| namespace MediaBrowser.Controller.Entities | namespace MediaBrowser.Controller.Entities | ||||||
| { | { | ||||||
| @ -11,6 +15,10 @@ namespace MediaBrowser.Controller.Entities | |||||||
| 
 | 
 | ||||||
|         public Guid Id { get; set; } |         public Guid Id { get; set; } | ||||||
| 
 | 
 | ||||||
|  |         public string Path { get; set; } | ||||||
|  | 
 | ||||||
|  |         public Folder Parent { get; set; } | ||||||
|  | 
 | ||||||
|         public string PrimaryImagePath { get; set; } |         public string PrimaryImagePath { get; set; } | ||||||
| 
 | 
 | ||||||
|         public DateTime DateCreated { get; set; } |         public DateTime DateCreated { get; set; } | ||||||
| @ -21,5 +29,45 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         { |         { | ||||||
|             return Name; |             return Name; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         protected ItemResolveEventArgs _resolveArgs; | ||||||
|  |         /// <summary> | ||||||
|  |         /// We attach these to the item so that we only ever have to hit the file system once | ||||||
|  |         /// (this includes the children of the containing folder) | ||||||
|  |         /// Use ResolveArgs.FileSystemChildren to check for the existence of files instead of File.Exists | ||||||
|  |         /// </summary> | ||||||
|  |         public ItemResolveEventArgs ResolveArgs | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_resolveArgs == null) | ||||||
|  |                 { | ||||||
|  |                     _resolveArgs = new ItemResolveEventArgs() | ||||||
|  |                     { | ||||||
|  |                         FileInfo = FileData.GetFileData(this.Path), | ||||||
|  |                         Parent = this.Parent, | ||||||
|  |                         Cancel = false, | ||||||
|  |                         Path = this.Path | ||||||
|  |                     }; | ||||||
|  |                     _resolveArgs = FileSystemHelper.FilterChildFileSystemEntries(_resolveArgs, (this.Parent != null && this.Parent.IsRoot)); | ||||||
|  |                 } | ||||||
|  |                 return _resolveArgs; | ||||||
|  |             } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 _resolveArgs = value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Refresh metadata on us by execution our provider chain | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>true if a provider reports we changed</returns> | ||||||
|  |         public bool RefreshMetadata() | ||||||
|  |         { | ||||||
|  |             Kernel.Instance.ExecuteMetadataProviders(this).ConfigureAwait(false); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| using MediaBrowser.Model.Entities; | using MediaBrowser.Model.Entities; | ||||||
|  | using MediaBrowser.Controller.Library; | ||||||
|  | using MediaBrowser.Controller.IO; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| @ -14,10 +16,6 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public DateTime? PremiereDate { get; set; } |         public DateTime? PremiereDate { get; set; } | ||||||
| 
 | 
 | ||||||
|         public string Path { get; set; } |  | ||||||
| 
 |  | ||||||
|         public Folder Parent { get; set; } |  | ||||||
| 
 |  | ||||||
|         public string LogoImagePath { get; set; } |         public string LogoImagePath { get; set; } | ||||||
| 
 | 
 | ||||||
|         public string ArtImagePath { get; set; } |         public string ArtImagePath { get; set; } | ||||||
| @ -134,6 +132,18 @@ namespace MediaBrowser.Controller.Entities | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Determine if we have changed vs the passed in copy | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="original"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public virtual bool IsChanged(BaseItem original) | ||||||
|  |         { | ||||||
|  |             bool changed = original.DateModified != this.DateModified; | ||||||
|  |             changed |= original.DateCreated != this.DateCreated; | ||||||
|  |             return changed; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Determines if the item is considered new based on user settings |         /// Determines if the item is considered new based on user settings | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | |||||||
| @ -1,5 +1,10 @@ | |||||||
| using MediaBrowser.Model.Entities; | using MediaBrowser.Model.Entities; | ||||||
|  | using MediaBrowser.Controller.IO; | ||||||
|  | using MediaBrowser.Controller.Library; | ||||||
|  | using MediaBrowser.Common.Logging; | ||||||
|  | using MediaBrowser.Controller.Resolvers; | ||||||
| using System; | using System; | ||||||
|  | using System.Threading.Tasks; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| 
 | 
 | ||||||
| @ -7,6 +12,28 @@ namespace MediaBrowser.Controller.Entities | |||||||
| { | { | ||||||
|     public class Folder : BaseItem |     public class Folder : BaseItem | ||||||
|     { |     { | ||||||
|  |         #region Events | ||||||
|  |         /// <summary> | ||||||
|  |         /// Fires whenever a validation routine updates our children.  The added and removed children are properties of the args. | ||||||
|  |         /// *** Will fire asynchronously. *** | ||||||
|  |         /// </summary> | ||||||
|  |         public event EventHandler<ChildrenChangedEventArgs> ChildrenChanged; | ||||||
|  |         protected void OnChildrenChanged(ChildrenChangedEventArgs args) | ||||||
|  |         { | ||||||
|  |             if (ChildrenChanged != null) | ||||||
|  |             { | ||||||
|  |                 Task.Run( () =>  | ||||||
|  |                     { | ||||||
|  |                         ChildrenChanged(this, args); | ||||||
|  |                         Kernel.Instance.OnLibraryChanged(args); | ||||||
|  |                     }); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         public IEnumerable<string> PhysicalLocations { get; set; } | ||||||
|  | 
 | ||||||
|         public override bool IsFolder |         public override bool IsFolder | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
| @ -24,23 +51,45 @@ namespace MediaBrowser.Controller.Entities | |||||||
|                 return Parent != null && Parent.IsRoot; |                 return Parent != null && Parent.IsRoot; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 |         protected object childLock = new object(); | ||||||
|         public IEnumerable<BaseItem> Children { get; set; } |         protected List<BaseItem> children; | ||||||
| 
 |         protected virtual List<BaseItem> ActualChildren | ||||||
|         /// <summary> |  | ||||||
|         /// Gets allowed children of an item |  | ||||||
|         /// </summary> |  | ||||||
|         public IEnumerable<BaseItem> GetParentalAllowedChildren(User user) |  | ||||||
|         { |         { | ||||||
|             return Children.Where(c => c.IsParentalAllowed(user)); |             get | ||||||
|  |             { | ||||||
|  |                 if (children == null) | ||||||
|  |                 { | ||||||
|  |                     LoadChildren(); | ||||||
|  |                 } | ||||||
|  |                 return children; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 children = value; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets allowed recursive children of an item |         /// thread-safe access to the actual children of this folder - without regard to user | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetParentalAllowedRecursiveChildren(User user) |         public IEnumerable<BaseItem> Children | ||||||
|         { |         { | ||||||
|             foreach (var item in GetParentalAllowedChildren(user)) |             get | ||||||
|  |             { | ||||||
|  |                 lock (childLock) | ||||||
|  |                     return ActualChildren.ToList(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// thread-safe access to all recursive children of this folder - without regard to user | ||||||
|  |         /// </summary> | ||||||
|  |         public IEnumerable<BaseItem> RecursiveChildren | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 foreach (var item in Children) | ||||||
|                 { |                 { | ||||||
|                     yield return item; |                     yield return item; | ||||||
| 
 | 
 | ||||||
| @ -48,7 +97,228 @@ namespace MediaBrowser.Controller.Entities | |||||||
| 
 | 
 | ||||||
|                     if (subFolder != null) |                     if (subFolder != null) | ||||||
|                     { |                     { | ||||||
|                     foreach (var subitem in subFolder.GetParentalAllowedRecursiveChildren(user)) |                         foreach (var subitem in subFolder.RecursiveChildren) | ||||||
|  |                         { | ||||||
|  |                             yield return subitem; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |                  | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Loads and validates our children | ||||||
|  |         /// </summary> | ||||||
|  |         protected virtual void LoadChildren() | ||||||
|  |         { | ||||||
|  |             //first - load our children from the repo | ||||||
|  |             lock (childLock) | ||||||
|  |                 children = GetCachedChildren(); | ||||||
|  | 
 | ||||||
|  |             //then kick off a validation against the actual file system | ||||||
|  |             Task.Run(() => ValidateChildren()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected bool ChildrenValidating = false; | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes | ||||||
|  |         /// ***Currently does not contain logic to maintain items that are unavailable in the file system*** | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         protected async virtual void ValidateChildren() | ||||||
|  |         { | ||||||
|  |             if (ChildrenValidating) return; //only ever want one of these going at once and don't want them to fire off in sequence so don't use lock | ||||||
|  |             ChildrenValidating = true; | ||||||
|  |             bool changed = false; //this will save us a little time at the end if nothing changes | ||||||
|  |             var changedArgs = new ChildrenChangedEventArgs(this); | ||||||
|  |             //get the current valid children from filesystem (or wherever) | ||||||
|  |             var nonCachedChildren = await GetNonCachedChildren(); | ||||||
|  |             if (nonCachedChildren == null) return; //nothing to validate | ||||||
|  |             //build a dictionary of the current children we have now by Id so we can compare quickly and easily | ||||||
|  |             Dictionary<Guid, BaseItem> currentChildren; | ||||||
|  |             lock (childLock) | ||||||
|  |                 currentChildren =  ActualChildren.ToDictionary(i => i.Id); | ||||||
|  |              | ||||||
|  |             //create a list for our validated children | ||||||
|  |             var validChildren = new List<BaseItem>(); | ||||||
|  |             //now traverse the valid children and find any changed or new items | ||||||
|  |             foreach (var child in nonCachedChildren) | ||||||
|  |             { | ||||||
|  |                 BaseItem currentChild; | ||||||
|  |                 currentChildren.TryGetValue(child.Id, out currentChild); | ||||||
|  |                 if (currentChild == null) | ||||||
|  |                 { | ||||||
|  |                     //brand new item - needs to be added | ||||||
|  |                     changed = true; | ||||||
|  |                     changedArgs.ItemsAdded.Add(child); | ||||||
|  |                     //Logger.LogInfo("New Item Added to Library: ("+child.GetType().Name+")"+ child.Name + "(" + child.Path + ")"); | ||||||
|  |                     //refresh it | ||||||
|  |                     child.RefreshMetadata(); | ||||||
|  |                     //save it in repo... | ||||||
|  | 
 | ||||||
|  |                     //and add it to our valid children | ||||||
|  |                     validChildren.Add(child); | ||||||
|  |                     //fire an added event...? | ||||||
|  |                     //if it is a folder we need to validate its children as well | ||||||
|  |                     Folder folder = child as Folder; | ||||||
|  |                     if (folder != null) | ||||||
|  |                     { | ||||||
|  |                         folder.ValidateChildren(); | ||||||
|  |                         //probably need to refresh too... | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     //existing item - check if it has changed | ||||||
|  |                     if (currentChild.IsChanged(child)) | ||||||
|  |                     { | ||||||
|  |                         changed = true; | ||||||
|  |                         //update resolve args and refresh meta | ||||||
|  |                         //  Note - we are refreshing the existing child instead of the newly found one so the "Except" operation below | ||||||
|  |                         //  will identify this item as the same one | ||||||
|  |                         currentChild.ResolveArgs = child.ResolveArgs; | ||||||
|  |                         currentChild.RefreshMetadata(); | ||||||
|  |                         //save it in repo... | ||||||
|  |                         validChildren.Add(currentChild); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         //current child that didn't change - just put it in the valid children | ||||||
|  |                         validChildren.Add(currentChild); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //that's all the new and changed ones - now see if there are any that are missing | ||||||
|  |             changedArgs.ItemsRemoved = currentChildren.Values.Except(validChildren); | ||||||
|  |             changed |= changedArgs.ItemsRemoved != null; | ||||||
|  | 
 | ||||||
|  |             //now, if anything changed - replace our children | ||||||
|  |             if (changed) | ||||||
|  |             { | ||||||
|  |                 lock (childLock) | ||||||
|  |                     ActualChildren = validChildren; | ||||||
|  |                 //and save children in repo... | ||||||
|  | 
 | ||||||
|  |                 //and fire event | ||||||
|  |                 this.OnChildrenChanged(changedArgs); | ||||||
|  |             } | ||||||
|  |             ChildrenValidating = false; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get the children of this folder from the actual file system | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         protected async virtual Task<IEnumerable<BaseItem>> GetNonCachedChildren() | ||||||
|  |         { | ||||||
|  |             ItemResolveEventArgs args = new ItemResolveEventArgs() | ||||||
|  |             { | ||||||
|  |                 FileInfo = FileData.GetFileData(this.Path), | ||||||
|  |                 Parent = this.Parent, | ||||||
|  |                 Cancel = false, | ||||||
|  |                 Path = this.Path | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // Gather child folder and files | ||||||
|  |             if (args.IsDirectory) | ||||||
|  |             { | ||||||
|  |                 args.FileSystemChildren = FileData.GetFileSystemEntries(this.Path, "*").ToArray(); | ||||||
|  | 
 | ||||||
|  |                 bool isVirtualFolder = Parent != null && Parent.IsRoot; | ||||||
|  |                 args = FileSystemHelper.FilterChildFileSystemEntries(args, isVirtualFolder); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Logger.LogError("Folder has a path that is not a directory: " + this.Path); | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (!EntityResolutionHelper.ShouldResolvePathContents(args)) | ||||||
|  |             { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |             return (await Task.WhenAll<BaseItem>(GetChildren(args.FileSystemChildren)).ConfigureAwait(false)) | ||||||
|  |                         .Where(i => i != null).OrderBy(f => | ||||||
|  |                         { | ||||||
|  |                             return string.IsNullOrEmpty(f.SortName) ? f.Name : f.SortName; | ||||||
|  | 
 | ||||||
|  |                         }); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Resolves a path into a BaseItem | ||||||
|  |         /// </summary> | ||||||
|  |         protected async Task<BaseItem> GetChild(string path,  WIN32_FIND_DATA? fileInfo = null) | ||||||
|  |         { | ||||||
|  |             ItemResolveEventArgs args = new ItemResolveEventArgs() | ||||||
|  |             { | ||||||
|  |                 FileInfo = fileInfo ?? FileData.GetFileData(path), | ||||||
|  |                 Parent = this, | ||||||
|  |                 Cancel = false, | ||||||
|  |                 Path = path | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); | ||||||
|  |             args = FileSystemHelper.FilterChildFileSystemEntries(args, false); | ||||||
|  | 
 | ||||||
|  |             return Kernel.Instance.ResolveItem(args); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Finds child BaseItems for a given Folder | ||||||
|  |         /// </summary> | ||||||
|  |         protected Task<BaseItem>[] GetChildren(WIN32_FIND_DATA[] fileSystemChildren) | ||||||
|  |         { | ||||||
|  |             Task<BaseItem>[] tasks = new Task<BaseItem>[fileSystemChildren.Length]; | ||||||
|  | 
 | ||||||
|  |             for (int i = 0; i < fileSystemChildren.Length; i++) | ||||||
|  |             { | ||||||
|  |                 var child = fileSystemChildren[i]; | ||||||
|  | 
 | ||||||
|  |                 tasks[i] = GetChild(child.Path, child); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return tasks; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get our children from the repo - stubbed for now | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         protected virtual List<BaseItem> GetCachedChildren() | ||||||
|  |         { | ||||||
|  |             return new List<BaseItem>(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets allowed children of an item | ||||||
|  |         /// </summary> | ||||||
|  |         public IEnumerable<BaseItem> GetChildren(User user) | ||||||
|  |         { | ||||||
|  |             return ActualChildren.Where(c => c.IsParentalAllowed(user)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets allowed recursive children of an item | ||||||
|  |         /// </summary> | ||||||
|  |         public IEnumerable<BaseItem> GetRecursiveChildren(User user) | ||||||
|  |         { | ||||||
|  |             foreach (var item in GetChildren(user)) | ||||||
|  |             { | ||||||
|  |                 yield return item; | ||||||
|  | 
 | ||||||
|  |                 var subFolder = item as Folder; | ||||||
|  | 
 | ||||||
|  |                 if (subFolder != null) | ||||||
|  |                 { | ||||||
|  |                     foreach (var subitem in subFolder.GetRecursiveChildren(user)) | ||||||
|                     { |                     { | ||||||
|                         yield return subitem; |                         yield return subitem; | ||||||
|                     } |                     } | ||||||
| @ -63,7 +333,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         { |         { | ||||||
|             var counts = new ItemSpecialCounts(); |             var counts = new ItemSpecialCounts(); | ||||||
| 
 | 
 | ||||||
|             IEnumerable<BaseItem> recursiveChildren = GetParentalAllowedRecursiveChildren(user); |             IEnumerable<BaseItem> recursiveChildren = GetRecursiveChildren(user); | ||||||
| 
 | 
 | ||||||
|             var recentlyAddedItems = GetRecentlyAddedItems(recursiveChildren, user); |             var recentlyAddedItems = GetRecentlyAddedItems(recursiveChildren, user); | ||||||
| 
 | 
 | ||||||
| @ -80,7 +350,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetItemsWithGenre(string genre, User user) |         public IEnumerable<BaseItem> GetItemsWithGenre(string genre, User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase))); |             return GetRecursiveChildren(user).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -88,7 +358,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetItemsWithYear(int year, User user) |         public IEnumerable<BaseItem> GetItemsWithYear(int year, User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year); |             return GetRecursiveChildren(user).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -96,7 +366,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetItemsWithStudio(string studio, User user) |         public IEnumerable<BaseItem> GetItemsWithStudio(string studio, User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase))); |             return GetRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -104,7 +374,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetFavoriteItems(User user) |         public IEnumerable<BaseItem> GetFavoriteItems(User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(c => |             return GetRecursiveChildren(user).Where(c => | ||||||
|             { |             { | ||||||
|                 UserItemData data = c.GetUserData(user, false); |                 UserItemData data = c.GetUserData(user, false); | ||||||
| 
 | 
 | ||||||
| @ -122,7 +392,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IEnumerable<BaseItem> GetItemsWithPerson(string person, User user) |         public IEnumerable<BaseItem> GetItemsWithPerson(string person, User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(c => |             return GetRecursiveChildren(user).Where(c => | ||||||
|             { |             { | ||||||
|                 if (c.People != null) |                 if (c.People != null) | ||||||
|                 { |                 { | ||||||
| @ -139,7 +409,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// <param name="personType">Specify this to limit results to a specific PersonType</param> |         /// <param name="personType">Specify this to limit results to a specific PersonType</param> | ||||||
|         public IEnumerable<BaseItem> GetItemsWithPerson(string person, string personType, User user) |         public IEnumerable<BaseItem> GetItemsWithPerson(string person, string personType, User user) | ||||||
|         { |         { | ||||||
|             return GetParentalAllowedRecursiveChildren(user).Where(c => |             return GetRecursiveChildren(user).Where(c => | ||||||
|             { |             { | ||||||
|                 if (c.People != null) |                 if (c.People != null) | ||||||
|                 { |                 { | ||||||
| @ -155,7 +425,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public List<BaseItem> GetRecentlyAddedItems(User user) |         public List<BaseItem> GetRecentlyAddedItems(User user) | ||||||
|         { |         { | ||||||
|             return GetRecentlyAddedItems(GetParentalAllowedRecursiveChildren(user), user); |             return GetRecentlyAddedItems(GetRecursiveChildren(user), user); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -163,7 +433,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public List<BaseItem> GetRecentlyAddedUnplayedItems(User user) |         public List<BaseItem> GetRecentlyAddedUnplayedItems(User user) | ||||||
|         { |         { | ||||||
|             return GetRecentlyAddedUnplayedItems(GetParentalAllowedRecursiveChildren(user), user); |             return GetRecentlyAddedUnplayedItems(GetRecursiveChildren(user), user); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -171,7 +441,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public List<BaseItem> GetInProgressItems(User user) |         public List<BaseItem> GetInProgressItems(User user) | ||||||
|         { |         { | ||||||
|             return GetInProgressItems(GetParentalAllowedRecursiveChildren(user), user); |             return GetInProgressItems(GetRecursiveChildren(user), user); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -288,7 +558,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|             base.SetPlayedStatus(user, wasPlayed); |             base.SetPlayedStatus(user, wasPlayed); | ||||||
| 
 | 
 | ||||||
|             // Now sweep through recursively and update status |             // Now sweep through recursively and update status | ||||||
|             foreach (BaseItem item in GetParentalAllowedChildren(user)) |             foreach (BaseItem item in GetChildren(user)) | ||||||
|             { |             { | ||||||
|                 item.SetPlayedStatus(user, wasPlayed); |                 item.SetPlayedStatus(user, wasPlayed); | ||||||
|             } |             } | ||||||
| @ -306,7 +576,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|                 return result; |                 return result; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             foreach (BaseItem item in Children) |             foreach (BaseItem item in ActualChildren) | ||||||
|             { |             { | ||||||
|                 result = item.FindItemById(id); |                 result = item.FindItemById(id); | ||||||
| 
 | 
 | ||||||
| @ -329,7 +599,7 @@ namespace MediaBrowser.Controller.Entities | |||||||
|                 return this; |                 return this; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             foreach (BaseItem item in Children) |             foreach (BaseItem item in ActualChildren) | ||||||
|             { |             { | ||||||
|                 var folder = item as Folder; |                 var folder = item as Folder; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| using MediaBrowser.Controller.Entities; | using MediaBrowser.Controller.Entities; | ||||||
|  | using MediaBrowser.Common.Logging; | ||||||
|  | using MediaBrowser.Common.Extensions; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
| @ -26,23 +28,18 @@ namespace MediaBrowser.Controller.IO | |||||||
| 
 | 
 | ||||||
|             foreach (Folder folder in rootFolder.Children.OfType<Folder>()) |             foreach (Folder folder in rootFolder.Children.OfType<Folder>()) | ||||||
|             { |             { | ||||||
|                 foreach (Folder subFolder in folder.Children.OfType<Folder>()) |                 foreach (string path in folder.PhysicalLocations) | ||||||
|                 { |                 { | ||||||
|                     if (Path.IsPathRooted(subFolder.Path)) |                     if (Path.IsPathRooted(path) && !pathsToWatch.ContainsStartsWith(path)) | ||||||
|                     { |                     { | ||||||
|                         string parent = Path.GetDirectoryName(subFolder.Path); |                         pathsToWatch.Add(path); | ||||||
| 
 |  | ||||||
|                         if (!pathsToWatch.Contains(parent)) |  | ||||||
|                         { |  | ||||||
|                             pathsToWatch.Add(parent); |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             foreach (string path in pathsToWatch) |             foreach (string path in pathsToWatch) | ||||||
|             { |             { | ||||||
|                 var watcher = new FileSystemWatcher(path, "*") { }; |                 Logger.LogInfo("Watching directory " + path + " for changes."); | ||||||
| 
 | 
 | ||||||
|                 watcher.IncludeSubdirectories = true; |                 watcher.IncludeSubdirectories = true; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										86
									
								
								MediaBrowser.Controller/IO/FileSystemHelper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								MediaBrowser.Controller/IO/FileSystemHelper.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using MediaBrowser.Controller.Resolvers; | ||||||
|  | using MediaBrowser.Controller.Library; | ||||||
|  | 
 | ||||||
|  | namespace MediaBrowser.Controller.IO | ||||||
|  | { | ||||||
|  |     public static class FileSystemHelper | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Transforms shortcuts into their actual paths and filters out items that should be ignored | ||||||
|  |         /// </summary> | ||||||
|  |         public static ItemResolveEventArgs FilterChildFileSystemEntries(ItemResolveEventArgs args, bool flattenShortcuts) | ||||||
|  |         { | ||||||
|  |              | ||||||
|  |             List<WIN32_FIND_DATA> returnChildren = new List<WIN32_FIND_DATA>(); | ||||||
|  |             List<WIN32_FIND_DATA> resolvedShortcuts = new List<WIN32_FIND_DATA>(); | ||||||
|  | 
 | ||||||
|  |             foreach (var file in args.FileSystemChildren) | ||||||
|  |             { | ||||||
|  |                 // If it's a shortcut, resolve it | ||||||
|  |                 if (Shortcut.IsShortcut(file.Path)) | ||||||
|  |                 { | ||||||
|  |                     string newPath = Shortcut.ResolveShortcut(file.Path); | ||||||
|  |                     WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath); | ||||||
|  | 
 | ||||||
|  |                     // Find out if the shortcut is pointing to a directory or file | ||||||
|  |                     if (newPathData.IsDirectory) | ||||||
|  |                     { | ||||||
|  |                         // add to our physical locations | ||||||
|  |                         args.AdditionalLocations.Add(newPath); | ||||||
|  | 
 | ||||||
|  |                         // If we're flattening then get the shortcut's children | ||||||
|  |                         if (flattenShortcuts) | ||||||
|  |                         { | ||||||
|  |                             returnChildren.Add(file); | ||||||
|  |                             ItemResolveEventArgs newArgs = new ItemResolveEventArgs() | ||||||
|  |                             { | ||||||
|  |                                 FileSystemChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray() | ||||||
|  |                             }; | ||||||
|  | 
 | ||||||
|  |                             resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newArgs, false).FileSystemChildren); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             returnChildren.Add(newPathData); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         returnChildren.Add(newPathData); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     //not a shortcut check to see if we should filter it out | ||||||
|  |                     if (EntityResolutionHelper.ShouldResolvePath(file)) | ||||||
|  |                     { | ||||||
|  |                         returnChildren.Add(file); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         //filtered - see if it is one of our "indicator" folders and mark it now - no reason to search for it again | ||||||
|  |                         args.IsBDFolder |= file.cFileName.Equals("bdmv", StringComparison.OrdinalIgnoreCase); | ||||||
|  |                         args.IsDVDFolder |= file.cFileName.Equals("video_ts", StringComparison.OrdinalIgnoreCase); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (resolvedShortcuts.Count > 0) | ||||||
|  |             { | ||||||
|  |                 resolvedShortcuts.InsertRange(0, returnChildren); | ||||||
|  |                 args.FileSystemChildren = resolvedShortcuts.ToArray(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 args.FileSystemChildren = returnChildren.ToArray(); | ||||||
|  |             } | ||||||
|  |             return args; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -179,7 +179,7 @@ namespace MediaBrowser.Controller.IO | |||||||
| 
 | 
 | ||||||
|         public static bool IsShortcut(string filename) |         public static bool IsShortcut(string filename) | ||||||
|         { |         { | ||||||
|             return Path.GetExtension(filename).EndsWith("lnk", StringComparison.OrdinalIgnoreCase); |             return filename != null ? Path.GetExtension(filename).EndsWith("lnk", StringComparison.OrdinalIgnoreCase) : false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ using MediaBrowser.Controller.Weather; | |||||||
| using MediaBrowser.Model.Authentication; | using MediaBrowser.Model.Authentication; | ||||||
| using MediaBrowser.Model.Configuration; | using MediaBrowser.Model.Configuration; | ||||||
| using MediaBrowser.Model.Progress; | using MediaBrowser.Model.Progress; | ||||||
|  | using MediaBrowser.Common.Extensions; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.Composition; | using System.ComponentModel.Composition; | ||||||
| @ -24,6 +25,21 @@ namespace MediaBrowser.Controller | |||||||
| { | { | ||||||
|     public class Kernel : BaseKernel<ServerConfiguration, ServerApplicationPaths> |     public class Kernel : BaseKernel<ServerConfiguration, ServerApplicationPaths> | ||||||
|     { |     { | ||||||
|  |         #region Events | ||||||
|  |         /// <summary> | ||||||
|  |         /// Fires whenever any validation routine adds or removes items.  The added and removed items are properties of the args. | ||||||
|  |         /// *** Will fire asynchronously. *** | ||||||
|  |         /// </summary> | ||||||
|  |         public event EventHandler<ChildrenChangedEventArgs> LibraryChanged; | ||||||
|  |         public void OnLibraryChanged(ChildrenChangedEventArgs args) | ||||||
|  |         { | ||||||
|  |             if (LibraryChanged != null) | ||||||
|  |             { | ||||||
|  |                 Task.Run(() => LibraryChanged(this, args)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|         public static Kernel Instance { get; private set; } |         public static Kernel Instance { get; private set; } | ||||||
| 
 | 
 | ||||||
|         public ItemController ItemController { get; private set; } |         public ItemController ItemController { get; private set; } | ||||||
| @ -88,8 +104,6 @@ namespace MediaBrowser.Controller | |||||||
|             ItemController = new ItemController(); |             ItemController = new ItemController(); | ||||||
|             DirectoryWatchers = new DirectoryWatchers(); |             DirectoryWatchers = new DirectoryWatchers(); | ||||||
| 
 | 
 | ||||||
|             ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath; |  | ||||||
|             ItemController.BeginResolvePath += ItemController_BeginResolvePath; |  | ||||||
| 
 | 
 | ||||||
|             base.InitializeInternal(progress); |             base.InitializeInternal(progress); | ||||||
|         } |         } | ||||||
| @ -139,46 +153,21 @@ namespace MediaBrowser.Controller | |||||||
|             MetadataProviders = MetadataProvidersEnumerable.OrderBy(e => e.Priority).ToArray(); |             MetadataProviders = MetadataProvidersEnumerable.OrderBy(e => e.Priority).ToArray(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         public BaseItem ResolveItem(ItemResolveEventArgs args) | ||||||
|         /// Fires when a path is about to be resolved, but before child folders and files  |  | ||||||
|         /// have been collected from the file system. |  | ||||||
|         /// This gives us a chance to cancel it if needed, resulting in the path being ignored |  | ||||||
|         /// </summary> |  | ||||||
|         void ItemController_PreBeginResolvePath(object sender, PreBeginResolveEventArgs e) |  | ||||||
|         { |         { | ||||||
|             // Ignore hidden files and folders |             // Try first priority resolvers | ||||||
|             if (e.IsHidden || e.IsSystemFile) |             for (int i = 0; i < EntityResolvers.Length; i++) | ||||||
|             { |             { | ||||||
|                 e.Cancel = true; |                 var item = EntityResolvers[i].ResolvePath(args); | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             // Ignore any folders named "trailers" |                 if (item != null) | ||||||
|             else if (Path.GetFileName(e.Path).Equals("trailers", StringComparison.OrdinalIgnoreCase)) |  | ||||||
|                 { |                 { | ||||||
|                 e.Cancel = true; |                     item.ResolveArgs = args; | ||||||
|             } |                     return item; | ||||||
| 
 |  | ||||||
|             // Don't try and resolve files within the season metadata folder |  | ||||||
|             else if (Path.GetFileName(e.Path).Equals("metadata", StringComparison.OrdinalIgnoreCase) && e.IsDirectory) |  | ||||||
|             { |  | ||||||
|                 if (e.Parent is Season || e.Parent is Series) |  | ||||||
|                 { |  | ||||||
|                     e.Cancel = true; |  | ||||||
|                 } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |             return null; | ||||||
|         /// Fires when a path is about to be resolved, but after child folders and files  |  | ||||||
|         /// This gives us a chance to cancel it if needed, resulting in the path being ignored |  | ||||||
|         /// </summary> |  | ||||||
|         void ItemController_BeginResolvePath(object sender, ItemResolveEventArgs e) |  | ||||||
|         { |  | ||||||
|             if (e.ContainsFile(".ignore")) |  | ||||||
|             { |  | ||||||
|                 // Ignore any folders containing a file called .ignore |  | ||||||
|                 e.Cancel = true; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void ReloadUsers() |         private void ReloadUsers() | ||||||
| @ -203,12 +192,14 @@ namespace MediaBrowser.Controller | |||||||
|             DirectoryWatchers.Start(); |             DirectoryWatchers.Start(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static Guid GetMD5(string str) |         void RootFolder_ChildrenChanged(object sender, ChildrenChangedEventArgs e) | ||||||
|         { |         { | ||||||
|             using (var provider = new MD5CryptoServiceProvider()) |             Logger.LogDebugInfo("Root Folder Children Changed.  Added: " + e.ItemsAdded.Count + " Removed: " + e.ItemsRemoved.Count()); | ||||||
|             { |             //re-start the directory watchers | ||||||
|                 return new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(str))); |             DirectoryWatchers.Stop(); | ||||||
|             } |             DirectoryWatchers.Start(); | ||||||
|  |             var allChildren = RootFolder.RecursiveChildren; | ||||||
|  |             Logger.LogInfo(string.Format("Loading complete.  Movies: {0} Episodes: {1}", allChildren.OfType<Entities.Movies.Movie>().Count(), allChildren.OfType<Entities.TV.Episode>().Count())); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @ -247,7 +238,8 @@ namespace MediaBrowser.Controller | |||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 result.Success = GetMD5((password ?? string.Empty)).ToString().Equals(user.Password); |                 password = password ?? string.Empty; | ||||||
|  |                 result.Success = password.GetMD5().ToString().Equals(user.Password); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Update LastActivityDate and LastLoginDate, then save |             // Update LastActivityDate and LastLoginDate, then save | ||||||
| @ -286,7 +278,7 @@ namespace MediaBrowser.Controller | |||||||
| 
 | 
 | ||||||
|                 children.Insert(index, newItem); |                 children.Insert(index, newItem); | ||||||
| 
 | 
 | ||||||
|                 item.Parent.Children = children.ToArray(); |                 //item.Parent.ActualChildren = children.ToArray(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -323,7 +315,7 @@ namespace MediaBrowser.Controller | |||||||
|             user.Id = Guid.NewGuid(); |             user.Id = Guid.NewGuid(); | ||||||
|             user.LastLoginDate = DateTime.UtcNow.AddDays(-1); |             user.LastLoginDate = DateTime.UtcNow.AddDays(-1); | ||||||
|             user.LastActivityDate = DateTime.UtcNow.AddHours(-3); |             user.LastActivityDate = DateTime.UtcNow.AddHours(-3); | ||||||
|             user.Password = GetMD5("1234").ToString(); |             user.Password = ("1234").GetMD5().ToString(); | ||||||
|             list.Add(user); |             list.Add(user); | ||||||
| 
 | 
 | ||||||
|             user = new User { }; |             user = new User { }; | ||||||
| @ -357,7 +349,7 @@ namespace MediaBrowser.Controller | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Runs all metadata providers for an entity |         /// Runs all metadata providers for an entity | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         internal async Task ExecuteMetadataProviders(BaseEntity item, ItemResolveEventArgs args, bool allowInternetProviders = true) |         internal async Task ExecuteMetadataProviders(BaseEntity item, bool allowInternetProviders = true) | ||||||
|         { |         { | ||||||
|             // Run them sequentially in order of priority |             // Run them sequentially in order of priority | ||||||
|             for (int i = 0; i < MetadataProviders.Length; i++) |             for (int i = 0; i < MetadataProviders.Length; i++) | ||||||
| @ -378,7 +370,7 @@ namespace MediaBrowser.Controller | |||||||
| 
 | 
 | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     await provider.FetchAsync(item, args).ConfigureAwait(false); |                     await provider.FetchAsync(item, item.ResolveArgs).ConfigureAwait(false); | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
|                 { |                 { | ||||||
|  | |||||||
							
								
								
									
										34
									
								
								MediaBrowser.Controller/Library/ChildrenChangedEventArgs.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								MediaBrowser.Controller/Library/ChildrenChangedEventArgs.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using MediaBrowser.Controller.Entities; | ||||||
|  | 
 | ||||||
|  | namespace MediaBrowser.Controller.Library | ||||||
|  | { | ||||||
|  |     public class ChildrenChangedEventArgs : EventArgs | ||||||
|  |     { | ||||||
|  |         public Folder Folder { get; set; } | ||||||
|  |         public List<BaseItem> ItemsAdded { get; set; } | ||||||
|  |         public IEnumerable<BaseItem> ItemsRemoved { get; set; } | ||||||
|  | 
 | ||||||
|  |         public ChildrenChangedEventArgs() | ||||||
|  |         { | ||||||
|  |             //initialize the list | ||||||
|  |             ItemsAdded = new List<BaseItem>(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Create the args and set the folder property | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="folder"></param> | ||||||
|  |         public ChildrenChangedEventArgs(Folder folder) | ||||||
|  |         { | ||||||
|  |             //init the folder property | ||||||
|  |             this.Folder = folder; | ||||||
|  |             //init the list | ||||||
|  |             ItemsAdded = new List<BaseItem>(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,5 +1,7 @@ | |||||||
| using MediaBrowser.Controller.Entities; | using MediaBrowser.Controller.Entities; | ||||||
| using MediaBrowser.Controller.IO; | using MediaBrowser.Controller.IO; | ||||||
|  | using MediaBrowser.Controller.Resolvers; | ||||||
|  | using MediaBrowser.Common.Extensions; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| @ -11,57 +13,21 @@ namespace MediaBrowser.Controller.Library | |||||||
| { | { | ||||||
|     public class ItemController |     public class ItemController | ||||||
|     { |     { | ||||||
|         #region PreBeginResolvePath Event |         //private BaseItem ResolveItem(ItemResolveEventArgs args) | ||||||
|         /// <summary> |         //{ | ||||||
|         /// Fires when a path is about to be resolved, but before child folders and files  |         //    // Try first priority resolvers | ||||||
|         /// have been collected from the file system. |         //    for (int i = 0; i < Kernel.Instance.EntityResolvers.Length; i++) | ||||||
|         /// This gives listeners a chance to cancel the operation and cause the path to be ignored. |         //    { | ||||||
|         /// </summary> |         //        var item = Kernel.Instance.EntityResolvers[i].ResolvePath(args); | ||||||
|         public event EventHandler<PreBeginResolveEventArgs> PreBeginResolvePath; |  | ||||||
|         private bool OnPreBeginResolvePath(PreBeginResolveEventArgs args) |  | ||||||
|         { |  | ||||||
|             if (PreBeginResolvePath != null) |  | ||||||
|             { |  | ||||||
|                 PreBeginResolvePath(this, args); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             return !args.Cancel; |         //        if (item != null) | ||||||
|         } |         //        { | ||||||
|         #endregion |         //            return item; | ||||||
|  |         //        } | ||||||
|  |         //    } | ||||||
| 
 | 
 | ||||||
|         #region BeginResolvePath Event |         //    return null; | ||||||
|         /// <summary> |         //} | ||||||
|         /// Fires when a path is about to be resolved, but after child folders and files  |  | ||||||
|         /// have been collected from the file system. |  | ||||||
|         /// This gives listeners a chance to cancel the operation and cause the path to be ignored. |  | ||||||
|         /// </summary> |  | ||||||
|         public event EventHandler<ItemResolveEventArgs> BeginResolvePath; |  | ||||||
|         private bool OnBeginResolvePath(ItemResolveEventArgs args) |  | ||||||
|         { |  | ||||||
|             if (BeginResolvePath != null) |  | ||||||
|             { |  | ||||||
|                 BeginResolvePath(this, args); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return !args.Cancel; |  | ||||||
|         } |  | ||||||
|         #endregion |  | ||||||
| 
 |  | ||||||
|         private BaseItem ResolveItem(ItemResolveEventArgs args) |  | ||||||
|         { |  | ||||||
|             // Try first priority resolvers |  | ||||||
|             for (int i = 0; i < Kernel.Instance.EntityResolvers.Length; i++) |  | ||||||
|             { |  | ||||||
|                 var item = Kernel.Instance.EntityResolvers[i].ResolvePath(args); |  | ||||||
| 
 |  | ||||||
|                 if (item != null) |  | ||||||
|                 { |  | ||||||
|                     return item; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Resolves a path into a BaseItem |         /// Resolves a path into a BaseItem | ||||||
| @ -76,122 +42,104 @@ namespace MediaBrowser.Controller.Library | |||||||
|                 Path = path |                 Path = path | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             if (!OnPreBeginResolvePath(args)) |  | ||||||
|             { |  | ||||||
|                 return null; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             WIN32_FIND_DATA[] fileSystemChildren; |  | ||||||
| 
 |  | ||||||
|             // Gather child folder and files |             // Gather child folder and files | ||||||
|             if (args.IsDirectory) |             if (args.IsDirectory) | ||||||
|             { |             { | ||||||
|                 fileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); |                 args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); | ||||||
| 
 | 
 | ||||||
|                 bool isVirtualFolder = parent != null && parent.IsRoot; |                 bool isVirtualFolder = parent != null && parent.IsRoot; | ||||||
|                 fileSystemChildren = FilterChildFileSystemEntries(fileSystemChildren, isVirtualFolder); |                 args = FileSystemHelper.FilterChildFileSystemEntries(args, isVirtualFolder); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 fileSystemChildren = new WIN32_FIND_DATA[] { }; |                 args.FileSystemChildren = new WIN32_FIND_DATA[] { }; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             args.FileSystemChildren = fileSystemChildren; |  | ||||||
| 
 | 
 | ||||||
|             // Fire BeginResolvePath to see if anyone wants to cancel this operation |             // Fire BeginResolvePath to see if anyone wants to cancel this operation | ||||||
|             if (!OnBeginResolvePath(args)) |             if (!EntityResolutionHelper.ShouldResolvePathContents(args)) | ||||||
|             { |             { | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             BaseItem item = ResolveItem(args); |             BaseItem item = Kernel.Instance.ResolveItem(args); | ||||||
| 
 |  | ||||||
|             if (item != null) |  | ||||||
|             { |  | ||||||
|                 await Kernel.Instance.ExecuteMetadataProviders(item, args, allowInternetProviders: allowInternetProviders).ConfigureAwait(false); |  | ||||||
| 
 |  | ||||||
|                 if (item.IsFolder) |  | ||||||
|                 { |  | ||||||
|                     // If it's a folder look for child entities |  | ||||||
|                     (item as Folder).Children = (await Task.WhenAll(GetChildren(item as Folder, fileSystemChildren, allowInternetProviders)).ConfigureAwait(false)) |  | ||||||
|                         .Where(i => i != null).OrderBy(f => (string.IsNullOrEmpty(f.SortName) ? f.Name : f.SortName)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             return item; |             return item; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         ///// <summary> | ||||||
|         /// Finds child BaseItems for a given Folder |         ///// Finds child BaseItems for a given Folder | ||||||
|         /// </summary> |         ///// </summary> | ||||||
|         private Task<BaseItem>[] GetChildren(Folder folder, WIN32_FIND_DATA[] fileSystemChildren, bool allowInternetProviders) |         //private Task<BaseItem>[] GetChildren(Folder folder, WIN32_FIND_DATA[] fileSystemChildren, bool allowInternetProviders) | ||||||
|         { |         //{ | ||||||
|             var tasks = new Task<BaseItem>[fileSystemChildren.Length]; |         //    Task<BaseItem>[] tasks = new Task<BaseItem>[fileSystemChildren.Length]; | ||||||
| 
 | 
 | ||||||
|             for (int i = 0; i < fileSystemChildren.Length; i++) |         //    for (int i = 0; i < fileSystemChildren.Length; i++) | ||||||
|             { |         //    { | ||||||
|                 var child = fileSystemChildren[i]; |         //        var child = fileSystemChildren[i]; | ||||||
| 
 | 
 | ||||||
|                 tasks[i] = GetItem(child.Path, folder, child, allowInternetProviders: allowInternetProviders); |         //        tasks[i] = GetItem(child.Path, folder, child, allowInternetProviders: allowInternetProviders); | ||||||
|             } |         //    } | ||||||
| 
 | 
 | ||||||
|             return tasks; |         //    return tasks; | ||||||
|         } |         //} | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         ///// <summary> | ||||||
|         /// Transforms shortcuts into their actual paths |         ///// Transforms shortcuts into their actual paths | ||||||
|         /// </summary> |         ///// </summary> | ||||||
|         private WIN32_FIND_DATA[] FilterChildFileSystemEntries(WIN32_FIND_DATA[] fileSystemChildren, bool flattenShortcuts) |         //private WIN32_FIND_DATA[] FilterChildFileSystemEntries(WIN32_FIND_DATA[] fileSystemChildren, bool flattenShortcuts) | ||||||
|         { |         //{ | ||||||
|             var returnArray = new WIN32_FIND_DATA[fileSystemChildren.Length]; |         //    WIN32_FIND_DATA[] returnArray = new WIN32_FIND_DATA[fileSystemChildren.Length]; | ||||||
|             var resolvedShortcuts = new List<WIN32_FIND_DATA>(); |         //    List<WIN32_FIND_DATA> resolvedShortcuts = new List<WIN32_FIND_DATA>(); | ||||||
| 
 | 
 | ||||||
|             for (int i = 0; i < fileSystemChildren.Length; i++) |         //    for (int i = 0; i < fileSystemChildren.Length; i++) | ||||||
|             { |         //    { | ||||||
|                 WIN32_FIND_DATA file = fileSystemChildren[i]; |         //        WIN32_FIND_DATA file = fileSystemChildren[i]; | ||||||
| 
 | 
 | ||||||
|                 // If it's a shortcut, resolve it |         //        // If it's a shortcut, resolve it | ||||||
|                 if (Shortcut.IsShortcut(file.Path)) |         //        if (Shortcut.IsShortcut(file.Path)) | ||||||
|                 { |         //        { | ||||||
|                     string newPath = Shortcut.ResolveShortcut(file.Path); |         //            string newPath = Shortcut.ResolveShortcut(file.Path); | ||||||
|                     WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath); |         //            WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath); | ||||||
| 
 | 
 | ||||||
|                     // Find out if the shortcut is pointing to a directory or file |         //            // Find out if the shortcut is pointing to a directory or file | ||||||
|                     if (newPathData.IsDirectory) |         //            if (newPathData.IsDirectory) | ||||||
|                     { |         //            { | ||||||
|                         // If we're flattening then get the shortcut's children |         //                // If we're flattening then get the shortcut's children | ||||||
| 
 | 
 | ||||||
|                         if (flattenShortcuts) |         //                if (flattenShortcuts) | ||||||
|                         { |         //                { | ||||||
|                             returnArray[i] = file; |         //                    returnArray[i] = file; | ||||||
|                             WIN32_FIND_DATA[] newChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray(); |         //                    WIN32_FIND_DATA[] newChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray(); | ||||||
| 
 | 
 | ||||||
|                             resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newChildren, false)); |         //                    resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newChildren, false)); | ||||||
|                         } |         //                } | ||||||
|                         else |         //                else | ||||||
|                         { |         //                { | ||||||
|                             returnArray[i] = newPathData; |         //                    returnArray[i] = newPathData; | ||||||
|                         } |         //                } | ||||||
|                     } |         //            } | ||||||
|                     else |         //            else | ||||||
|                     { |         //            { | ||||||
|                         returnArray[i] = newPathData; |         //                returnArray[i] = newPathData; | ||||||
|                     } |         //            } | ||||||
|                 } |         //        } | ||||||
|                 else |         //        else | ||||||
|                 { |         //        { | ||||||
|                     returnArray[i] = file; |         //            returnArray[i] = file; | ||||||
|                 } |         //        } | ||||||
|             } |         //    } | ||||||
| 
 | 
 | ||||||
|             if (resolvedShortcuts.Count > 0) |         //    if (resolvedShortcuts.Count > 0) | ||||||
|             { |         //    { | ||||||
|                 resolvedShortcuts.InsertRange(0, returnArray); |         //        resolvedShortcuts.InsertRange(0, returnArray); | ||||||
|                 return resolvedShortcuts.ToArray(); |         //        return resolvedShortcuts.ToArray(); | ||||||
|             } |         //    } | ||||||
| 
 |         //    else | ||||||
|             return returnArray; |         //    { | ||||||
|         } |         //        return returnArray; | ||||||
|  |         //    } | ||||||
|  |         //} | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets a Person |         /// Gets a Person | ||||||
| @ -255,7 +203,7 @@ namespace MediaBrowser.Controller.Library | |||||||
|             var item = new T { }; |             var item = new T { }; | ||||||
| 
 | 
 | ||||||
|             item.Name = name; |             item.Name = name; | ||||||
|             item.Id = Kernel.GetMD5(path); |             item.Id = path.GetMD5(); | ||||||
| 
 | 
 | ||||||
|             if (!Directory.Exists(path)) |             if (!Directory.Exists(path)) | ||||||
|             { |             { | ||||||
| @ -269,7 +217,7 @@ namespace MediaBrowser.Controller.Library | |||||||
|             args.FileInfo = FileData.GetFileData(path); |             args.FileInfo = FileData.GetFileData(path); | ||||||
|             args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); |             args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); | ||||||
| 
 | 
 | ||||||
|             await Kernel.Instance.ExecuteMetadataProviders(item, args).ConfigureAwait(false); |             await Kernel.Instance.ExecuteMetadataProviders(item).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             return item; |             return item; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| using MediaBrowser.Controller.Entities; | using MediaBrowser.Controller.Entities; | ||||||
| using MediaBrowser.Controller.IO; | using MediaBrowser.Controller.IO; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| 
 | 
 | ||||||
| @ -12,32 +14,39 @@ namespace MediaBrowser.Controller.Library | |||||||
|     { |     { | ||||||
|         public WIN32_FIND_DATA[] FileSystemChildren { get; set; } |         public WIN32_FIND_DATA[] FileSystemChildren { get; set; } | ||||||
| 
 | 
 | ||||||
|  |         protected List<string> _additionalLocations = new List<string>(); | ||||||
|  |         public List<string> AdditionalLocations | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 return _additionalLocations; | ||||||
|  |             } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 _additionalLocations = value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public IEnumerable<string> PhysicalLocations | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 return (new List<string>() {this.Path}).Concat(AdditionalLocations); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool IsBDFolder { get; set; } | ||||||
|  |         public bool IsDVDFolder { get; set; } | ||||||
|  | 
 | ||||||
|         public WIN32_FIND_DATA? GetFileSystemEntry(string path) |         public WIN32_FIND_DATA? GetFileSystemEntry(string path) | ||||||
|         { |         { | ||||||
|             for (int i = 0; i < FileSystemChildren.Length; i++) |             WIN32_FIND_DATA entry = FileSystemChildren.FirstOrDefault(f => f.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); | ||||||
|             { |             return entry.cFileName != null ? (WIN32_FIND_DATA?)entry : null; | ||||||
|                 WIN32_FIND_DATA entry = FileSystemChildren[i]; |  | ||||||
| 
 |  | ||||||
|                 if (entry.Path.Equals(path, StringComparison.OrdinalIgnoreCase)) |  | ||||||
|                 { |  | ||||||
|                     return entry; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             |  | ||||||
|             return null; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public bool ContainsFile(string name) |         public bool ContainsFile(string name) | ||||||
|         { |         { | ||||||
|             for (int i = 0; i < FileSystemChildren.Length; i++) |             return FileSystemChildren.FirstOrDefault(f => f.cFileName.Equals(name, StringComparison.OrdinalIgnoreCase)).cFileName != null; | ||||||
|             { |  | ||||||
|                 if (FileSystemChildren[i].cFileName.Equals(name, StringComparison.OrdinalIgnoreCase)) |  | ||||||
|                 { |  | ||||||
|                     return true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return false; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public bool ContainsFolder(string name) |         public bool ContainsFolder(string name) | ||||||
|  | |||||||
| @ -74,6 +74,8 @@ | |||||||
|     <Compile Include="Entities\UserItemData.cs" /> |     <Compile Include="Entities\UserItemData.cs" /> | ||||||
|     <Compile Include="Entities\Video.cs" /> |     <Compile Include="Entities\Video.cs" /> | ||||||
|     <Compile Include="Entities\Year.cs" /> |     <Compile Include="Entities\Year.cs" /> | ||||||
|  |     <Compile Include="IO\FileSystemHelper.cs" /> | ||||||
|  |     <Compile Include="Library\ChildrenChangedEventArgs.cs" /> | ||||||
|     <Compile Include="Providers\Movies\MovieProviderFromXml.cs" /> |     <Compile Include="Providers\Movies\MovieProviderFromXml.cs" /> | ||||||
|     <Compile Include="Providers\Movies\MovieSpecialFeaturesProvider.cs" /> |     <Compile Include="Providers\Movies\MovieSpecialFeaturesProvider.cs" /> | ||||||
|     <Compile Include="Providers\TV\EpisodeImageFromMediaLocationProvider.cs" /> |     <Compile Include="Providers\TV\EpisodeImageFromMediaLocationProvider.cs" /> | ||||||
| @ -81,6 +83,7 @@ | |||||||
|     <Compile Include="Providers\TV\EpisodeXmlParser.cs" /> |     <Compile Include="Providers\TV\EpisodeXmlParser.cs" /> | ||||||
|     <Compile Include="Providers\TV\SeriesProviderFromXml.cs" /> |     <Compile Include="Providers\TV\SeriesProviderFromXml.cs" /> | ||||||
|     <Compile Include="Providers\TV\SeriesXmlParser.cs" /> |     <Compile Include="Providers\TV\SeriesXmlParser.cs" /> | ||||||
|  |     <Compile Include="Resolvers\EntityResolutionHelper.cs" /> | ||||||
|     <Compile Include="Resolvers\Movies\BoxSetResolver.cs" /> |     <Compile Include="Resolvers\Movies\BoxSetResolver.cs" /> | ||||||
|     <Compile Include="Resolvers\Movies\MovieResolver.cs" /> |     <Compile Include="Resolvers\Movies\MovieResolver.cs" /> | ||||||
|     <Compile Include="Resolvers\TV\EpisodeResolver.cs" /> |     <Compile Include="Resolvers\TV\EpisodeResolver.cs" /> | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| using MediaBrowser.Controller.Entities; | using MediaBrowser.Controller.Entities; | ||||||
| using MediaBrowser.Controller.IO; | using MediaBrowser.Controller.IO; | ||||||
| using MediaBrowser.Controller.Library; | using MediaBrowser.Controller.Library; | ||||||
|  | using MediaBrowser.Common.Extensions; | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| 
 | 
 | ||||||
| @ -39,7 +40,7 @@ namespace MediaBrowser.Controller.Resolvers | |||||||
|                 item.Parent = args.Parent; |                 item.Parent = args.Parent; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             item.Id = Kernel.GetMD5(item.Path); |             item.Id = (item.GetType().FullName + item.Path).GetMD5(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public BaseItem ResolvePath(ItemResolveEventArgs args) |         public BaseItem ResolvePath(ItemResolveEventArgs args) | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using System.IO; | ||||||
|  | using MediaBrowser.Controller.IO; | ||||||
|  | using MediaBrowser.Controller.Library; | ||||||
|  | using MediaBrowser.Controller.Entities.TV; | ||||||
|  | 
 | ||||||
|  | namespace MediaBrowser.Controller.Resolvers | ||||||
|  | { | ||||||
|  |     public static class EntityResolutionHelper | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Any folder named in this list will be ignored - can be added to at runtime for extensibility | ||||||
|  |         /// </summary> | ||||||
|  |         public static List<string> IgnoreFolders = new List<string>() | ||||||
|  |         { | ||||||
|  |             "trailers", | ||||||
|  |             "metadata", | ||||||
|  |             "bdmv", | ||||||
|  |             "certificate", | ||||||
|  |             "backup", | ||||||
|  |             "video_ts", | ||||||
|  |             "audio_ts", | ||||||
|  |             "ps3_update", | ||||||
|  |             "ps3_vprm" | ||||||
|  |         }; | ||||||
|  |         /// <summary> | ||||||
|  |         /// Determines whether a path should be resolved or ignored entirely - called before we even look at the contents | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="path"></param> | ||||||
|  |         /// <returns>false if the path should be ignored</returns> | ||||||
|  |         public static bool ShouldResolvePath(WIN32_FIND_DATA path) | ||||||
|  |         { | ||||||
|  |             bool resolve = true; | ||||||
|  |             // Ignore hidden files and folders | ||||||
|  |             if (path.IsHidden || path.IsSystemFile) | ||||||
|  |             { | ||||||
|  |                 resolve = false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Ignore any folders in our list | ||||||
|  |             else if (path.IsDirectory && IgnoreFolders.Contains(Path.GetFileName(path.Path), StringComparer.OrdinalIgnoreCase)) | ||||||
|  |             { | ||||||
|  |                 resolve =  false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return resolve; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Determines whether a path should be ignored based on its contents - called after the contents have been read | ||||||
|  |         /// </summary> | ||||||
|  |         public static bool ShouldResolvePathContents(ItemResolveEventArgs args) | ||||||
|  |         { | ||||||
|  |             bool resolve = true; | ||||||
|  |             if (args.ContainsFile(".ignore")) | ||||||
|  |             { | ||||||
|  |                 // Ignore any folders containing a file called .ignore | ||||||
|  |                 resolve = false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return resolve; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Resolvers | |||||||
|         { |         { | ||||||
|             if (args.IsDirectory) |             if (args.IsDirectory) | ||||||
|             { |             { | ||||||
|                 return new Folder(); |                 return new Folder() { PhysicalLocations = args.PhysicalLocations }; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return null; |             return null; | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ using MediaBrowser.Controller.IO; | |||||||
| using MediaBrowser.Controller.Library; | using MediaBrowser.Controller.Library; | ||||||
| using MediaBrowser.Model.Entities; | using MediaBrowser.Model.Entities; | ||||||
| using System.ComponentModel.Composition; | using System.ComponentModel.Composition; | ||||||
|  | using System.Collections.Generic; | ||||||
| 
 | 
 | ||||||
| namespace MediaBrowser.Controller.Resolvers.Movies | namespace MediaBrowser.Controller.Resolvers.Movies | ||||||
| { | { | ||||||
| @ -61,12 +62,27 @@ namespace MediaBrowser.Controller.Resolvers.Movies | |||||||
| 
 | 
 | ||||||
|         private Movie GetMovie(ItemResolveEventArgs args) |         private Movie GetMovie(ItemResolveEventArgs args) | ||||||
|         { |         { | ||||||
|             // Loop through each child file/folder and see if we find a video |             //first see if the discovery process has already determined we are a DVD or BD | ||||||
|             for (var i = 0; i < args.FileSystemChildren.Length; i++) |             if (args.IsDVDFolder) | ||||||
|             { |             { | ||||||
|                 var child = args.FileSystemChildren[i]; |                 return new Movie() | ||||||
|  |                 { | ||||||
|  |                     Path = args.Path, | ||||||
|  |                     VideoType = VideoType.DVD | ||||||
|  |                 }; | ||||||
|  |             } | ||||||
|  |             else if (args.IsBDFolder) | ||||||
|  |             { | ||||||
|  |                 return new Movie() | ||||||
|  |                 { | ||||||
|  |                     Path = args.Path, | ||||||
|  |                     VideoType = VideoType.BluRay | ||||||
|  |                 }; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|                 var childArgs = new ItemResolveEventArgs |             // Loop through each child file/folder and see if we find a video | ||||||
|  |             foreach (var child in args.FileSystemChildren) | ||||||
|  |             { | ||||||
|                 { |                 { | ||||||
|                     FileInfo = child, |                     FileInfo = child, | ||||||
|                     FileSystemChildren = new WIN32_FIND_DATA[] { }, |                     FileSystemChildren = new WIN32_FIND_DATA[] { }, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user