diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1cbe5b635c..794ff86fdd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -89,6 +89,9 @@ namespace MediaBrowser.Controller.Entities /// The path. public virtual string Path { get; set; } + [IgnoreDataMember] + protected internal bool IsOffline { get; set; } + /// /// Gets or sets the type of the location. /// @@ -97,6 +100,11 @@ namespace MediaBrowser.Controller.Entities { get { + if (IsOffline) + { + return LocationType.Offline; + } + if (string.IsNullOrEmpty(Path)) { return LocationType.Virtual; @@ -649,13 +657,20 @@ namespace MediaBrowser.Controller.Entities // Support xbmc trailers (-trailer suffix on video file names) files.AddRange(resolveArgs.FileSystemChildren.Where(i => { - if ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) + try { - if (System.IO.Path.GetFileNameWithoutExtension(i.Name).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase)) + if ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) { - return true; + if (System.IO.Path.GetFileNameWithoutExtension(i.Name).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } } } + catch (IOException ex) + { + Logger.ErrorException("Error accessing path {0}", ex, i.FullName); + } return false; })); diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 297d513e5b..cab3058ef3 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -703,15 +703,23 @@ namespace MediaBrowser.Controller.Entities foreach (var item in itemsRemoved) { - BaseItem removed; - - if (!_children.TryRemove(item.Id, out removed)) + if (IsRootPathAvailable(item.Path)) { - Logger.Error("Failed to remove {0}", item.Name); + BaseItem removed; + + if (!_children.TryRemove(item.Id, out removed)) + { + Logger.Error("Failed to remove {0}", item.Name); + } + else + { + LibraryManager.ReportItemRemoved(item); + } + item.IsOffline = false; } else { - LibraryManager.ReportItemRemoved(item); + item.IsOffline = true; } } @@ -835,6 +843,28 @@ namespace MediaBrowser.Controller.Entities await Task.WhenAll(tasks).ConfigureAwait(false); } + /// + /// Determines if a path's root is available or not + /// + /// + /// + private bool IsRootPathAvailable(string path) + { + var parent = System.IO.Path.GetDirectoryName(path); + + while (!string.IsNullOrEmpty(parent) && !parent.ToCharArray()[0].Equals(System.IO.Path.DirectorySeparatorChar)) + { + if (Directory.Exists(parent)) + { + return true; + } + + parent = System.IO.Path.GetDirectoryName(path); + } + + return false; + } + /// /// Get the children of this folder from the actual file system /// @@ -973,7 +1003,7 @@ namespace MediaBrowser.Controller.Entities { var changed = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false); - return changed || (SupportsLinkedChildren && RefreshLinkedChildren()); + return changed || (SupportsLinkedChildren && LocationType == LocationType.FileSystem && RefreshLinkedChildren()); } /// diff --git a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs index a8540f4bd1..a05266b0c4 100644 --- a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs @@ -390,12 +390,21 @@ namespace MediaBrowser.Controller.Providers /// true if XXXX, false otherwise private bool IncludeInFileStamp(FileSystemInfo file, string[] extensions) { - if ((file.Attributes & FileAttributes.Directory) == FileAttributes.Directory) + try { + if ((file.Attributes & FileAttributes.Directory) == FileAttributes.Directory) + { + return false; + } + + return extensions.Length == 0 || extensions.Contains(file.Extension, StringComparer.OrdinalIgnoreCase); + } + catch (IOException ex) + { + Logger.ErrorException("Error accessing file attributes for {0}", ex, file.FullName); + return false; } - - return extensions.Length == 0 || extensions.Contains(file.Extension, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Model/Entities/LocationType.cs b/MediaBrowser.Model/Entities/LocationType.cs index 3adf030247..e6c2a843ba 100644 --- a/MediaBrowser.Model/Entities/LocationType.cs +++ b/MediaBrowser.Model/Entities/LocationType.cs @@ -17,6 +17,10 @@ namespace MediaBrowser.Model.Entities /// /// The virtual /// - Virtual + Virtual, + /// + /// The offline + /// + Offline } }