using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using MediaBrowser.Common.Kernel; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Progress; namespace MediaBrowser.Controller { public class Kernel : BaseKernel { public static Kernel Instance { get; private set; } public ItemController ItemController { get; private set; } public IEnumerable Users { get; private set; } public Folder RootFolder { get; private set; } private DirectoryWatchers DirectoryWatchers { get; set; } private string MediaRootFolderPath { get { return ApplicationPaths.RootFolderPath; } } /// /// Gets the list of currently registered metadata prvoiders /// [ImportMany(typeof(BaseMetadataProvider))] public IEnumerable MetadataProviders { get; private set; } /// /// Gets the list of currently registered entity resolvers /// [ImportMany(typeof(IBaseItemResolver))] public IEnumerable EntityResolvers { get; private set; } /// /// Creates a kernel based on a Data path, which is akin to our current programdata path /// public Kernel() : base() { Instance = this; ItemController = new ItemController(); DirectoryWatchers = new DirectoryWatchers(); ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath; ItemController.BeginResolvePath += ItemController_BeginResolvePath; } public async override Task Init(IProgress progress) { await base.Init(progress); progress.Report(new TaskProgress() { Description = "Loading Users", PercentComplete = 15 }); ReloadUsers(); progress.Report(new TaskProgress() { Description = "Loading Media Library", PercentComplete = 20 }); await ReloadRoot(); progress.Report(new TaskProgress() { Description = "Loading Complete", PercentComplete = 100 }); } protected override void OnComposablePartsLoaded() { AddCoreResolvers(); AddCoreProviders(); // The base class will start up all the plugins base.OnComposablePartsLoaded(); } private void AddCoreResolvers() { List list = EntityResolvers.ToList(); // Add the core resolvers list.AddRange(new IBaseItemResolver[]{ new AudioResolver(), new VideoResolver(), new VirtualFolderResolver(), new FolderResolver() }); EntityResolvers = list; } private void AddCoreProviders() { List list = MetadataProviders.ToList(); // Add the core resolvers list.InsertRange(0, new BaseMetadataProvider[]{ new ImageFromMediaLocationProvider(), new LocalTrailerProvider(), new AudioInfoProvider(), new FolderProviderFromXml() }); MetadataProviders = list; Parallel.ForEach(MetadataProviders, provider => { provider.Init(); }); } /// /// 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 /// void ItemController_PreBeginResolvePath(object sender, PreBeginResolveEventArgs e) { if (e.IsHidden || e.IsSystemFile) { // Ignore hidden files and folders e.Cancel = true; } else if (Path.GetFileName(e.Path).Equals("trailers", StringComparison.OrdinalIgnoreCase)) { // Ignore any folders named "trailers" e.Cancel = true; } } /// /// 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 /// void ItemController_BeginResolvePath(object sender, ItemResolveEventArgs e) { if (e.IsFolder) { if (e.ContainsFile(".ignore")) { // Ignore any folders containing a file called .ignore e.Cancel = true; } } } private void ReloadUsers() { Users = GetAllUsers(); } /// /// Reloads the root media folder /// public async Task ReloadRoot() { if (!Directory.Exists(MediaRootFolderPath)) { Directory.CreateDirectory(MediaRootFolderPath); } DirectoryWatchers.Stop(); RootFolder = await ItemController.GetItem(null, MediaRootFolderPath) as Folder; DirectoryWatchers.Start(); } private static MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider(); public static Guid GetMD5(string str) { lock (md5Provider) { return new Guid(md5Provider.ComputeHash(Encoding.Unicode.GetBytes(str))); } } public async Task ReloadItem(BaseItem item) { Folder folder = item as Folder; if (folder != null && folder.IsRoot) { await ReloadRoot(); } else { if (!Directory.Exists(item.Path) && !File.Exists(item.Path)) { await ReloadItem(item.Parent); return; } BaseItem newItem = await ItemController.GetItem(item.Parent, item.Path); List children = item.Parent.Children.ToList(); int index = children.IndexOf(item); children.RemoveAt(index); children.Insert(index, newItem); item.Parent.Children = children.ToArray(); } } /// /// Finds a library item by Id /// public BaseItem GetItemById(Guid id) { if (id == Guid.Empty) { return RootFolder; } return RootFolder.FindItemById(id); } /// /// Gets all users within the system /// private IEnumerable GetAllUsers() { List list = new List(); // Return a dummy user for now since all calls to get items requre a userId User user = new User(); user.Name = "Default User"; user.Id = Guid.Parse("5d1cf7fce25943b790d140095457a42b"); list.Add(user); return list; } } }