diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations/Library')
10 files changed, 388 insertions, 162 deletions
diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index ba7e33890..b550d1dda 100644 --- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -33,7 +33,8 @@ namespace MediaBrowser.Server.Implementations.Library // Synology "@eaDir", - "eaDir" + "eaDir", + "#recycle" }; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 442e2ebe5..b2302cf86 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -43,6 +43,7 @@ using MediaBrowser.Server.Implementations.Library.Resolvers; using MoreLinq; using SortOrder = MediaBrowser.Model.Entities.SortOrder; using VideoResolver = MediaBrowser.Naming.Video.VideoResolver; +using MediaBrowser.Common.Configuration; namespace MediaBrowser.Server.Implementations.Library { @@ -334,15 +335,6 @@ namespace MediaBrowser.Server.Implementations.Library } } - /// <summary> - /// Updates the item in library cache. - /// </summary> - /// <param name="item">The item.</param> - private void UpdateItemInLibraryCache(BaseItem item) - { - RegisterItem(item); - } - public void RegisterItem(BaseItem item) { if (item == null) @@ -695,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, - Folder parent, + Folder parent, LibraryOptions libraryOptions, string collectionType, IItemResolver[] resolvers) @@ -1216,12 +1208,7 @@ namespace MediaBrowser.Server.Implementations.Library if (libraryFolder != null) { info.ItemId = libraryFolder.Id.ToString("N"); - } - - var collectionFolder = libraryFolder as CollectionFolder; - if (collectionFolder != null) - { - info.LibraryOptions = collectionFolder.GetLibraryOptions(); + info.LibraryOptions = GetLibraryOptions(libraryFolder); } return info; @@ -1490,10 +1477,10 @@ namespace MediaBrowser.Server.Implementations.Library private void AddUserToQuery(InternalItemsQuery query, User user) { - if (query.AncestorIds.Length == 0 && - !query.ParentId.HasValue && - query.ChannelIds.Length == 0 && - query.TopParentIds.Length == 0 && + if (query.AncestorIds.Length == 0 && + !query.ParentId.HasValue && + query.ChannelIds.Length == 0 && + query.TopParentIds.Length == 0 && string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey) && query.ItemIds.Length == 0) { @@ -1781,7 +1768,7 @@ namespace MediaBrowser.Server.Implementations.Library foreach (var item in list) { - UpdateItemInLibraryCache(item); + RegisterItem(item); } if (ItemAdded != null) @@ -1822,7 +1809,7 @@ namespace MediaBrowser.Server.Implementations.Library await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false); - UpdateItemInLibraryCache(item); + RegisterItem(item); if (ItemUpdated != null) { @@ -1889,11 +1876,41 @@ namespace MediaBrowser.Server.Implementations.Library public LibraryOptions GetLibraryOptions(BaseItem item) { - var collectionFolder = GetCollectionFolders(item) - .OfType<CollectionFolder>() - .FirstOrDefault(); + var collectionFolder = item as CollectionFolder; + if (collectionFolder == null) + { + collectionFolder = GetCollectionFolders(item) + .OfType<CollectionFolder>() + .FirstOrDefault(); + } + + var options = collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions(); + + if (options.SchemaVersion < 3) + { + options.SaveLocalMetadata = ConfigurationManager.Configuration.SaveLocalMeta; + options.EnableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders; + } + + if (options.SchemaVersion < 2) + { + var chapterOptions = ConfigurationManager.GetConfiguration<ChapterOptions>("chapters"); + options.ExtractChapterImagesDuringLibraryScan = chapterOptions.ExtractDuringLibraryScan; - return collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions(); + if (collectionFolder != null) + { + if (string.Equals(collectionFolder.CollectionType, "movies", StringComparison.OrdinalIgnoreCase)) + { + options.EnableChapterImageExtraction = chapterOptions.EnableMovieChapterImageExtraction; + } + else if (string.Equals(collectionFolder.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + { + options.EnableChapterImageExtraction = chapterOptions.EnableEpisodeChapterImageExtraction; + } + } + } + + return options; } public string GetContentType(BaseItem item) @@ -2437,7 +2454,7 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) { - var files = owner.IsInMixedFolder ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory) + var files = owner.DetectIsInMixedFolder() ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory) .Where(i => string.Equals(i.Name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase)) .SelectMany(i => _fileSystem.GetFiles(i.FullName, false)) .ToList(); @@ -2527,8 +2544,60 @@ namespace MediaBrowser.Server.Implementations.Library }).OrderBy(i => i.Path).ToList(); } + public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) + { + if (ownerItem != null) + { + var libraryOptions = GetLibraryOptions(ownerItem); + if (libraryOptions != null) + { + foreach (var pathInfo in libraryOptions.PathInfos) + { + if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath)) + { + continue; + } + + var substitutionResult = SubstitutePathInternal(path, pathInfo.Path, pathInfo.NetworkPath); + if (substitutionResult.Item2) + { + return substitutionResult.Item1; + } + } + } + } + + var metadataPath = ConfigurationManager.Configuration.MetadataPath; + var metadataNetworkPath = ConfigurationManager.Configuration.MetadataNetworkPath; + + if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) + { + var metadataSubstitutionResult = SubstitutePathInternal(path, metadataPath, metadataNetworkPath); + if (metadataSubstitutionResult.Item2) + { + return metadataSubstitutionResult.Item1; + } + } + + foreach (var map in ConfigurationManager.Configuration.PathSubstitutions) + { + var substitutionResult = SubstitutePathInternal(path, map.From, map.To); + if (substitutionResult.Item2) + { + return substitutionResult.Item1; + } + } + + return path; + } + public string SubstitutePath(string path, string from, string to) { + return SubstitutePathInternal(path, from, to).Item1; + } + + private Tuple<string, bool> SubstitutePathInternal(string path, string from, string to) + { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); @@ -2542,7 +2611,11 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("to"); } + from = from.Trim(); + to = to.Trim(); + var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase); + var changed = false; if (!string.Equals(newPath, path)) { @@ -2554,9 +2627,11 @@ namespace MediaBrowser.Server.Implementations.Library { newPath = newPath.Replace('/', '\\'); } + + changed = true; } - return newPath; + return new Tuple<string, bool>(newPath, changed); } private void SetExtraTypeFromFilename(Video item) @@ -2685,7 +2760,7 @@ namespace MediaBrowser.Server.Implementations.Library throw new InvalidOperationException(); } - public void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary) + public void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary) { if (string.IsNullOrWhiteSpace(name)) { @@ -2703,12 +2778,13 @@ namespace MediaBrowser.Server.Implementations.Library virtualFolderPath = Path.Combine(rootFolderPath, name); } - if (mediaPaths != null) + var mediaPathInfos = options.PathInfos; + if (mediaPathInfos != null) { - var invalidpath = mediaPaths.FirstOrDefault(i => !_fileSystem.DirectoryExists(i)); + var invalidpath = mediaPathInfos.FirstOrDefault(i => !_fileSystem.DirectoryExists(i.Path)); if (invalidpath != null) { - throw new ArgumentException("The specified path does not exist: " + invalidpath + "."); + throw new ArgumentException("The specified path does not exist: " + invalidpath.Path + "."); } } @@ -2730,11 +2806,11 @@ namespace MediaBrowser.Server.Implementations.Library CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); - if (mediaPaths != null) + if (mediaPathInfos != null) { - foreach (var path in mediaPaths) + foreach (var path in mediaPathInfos) { - AddMediaPath(name, path); + AddMediaPathInternal(name, path, false); } } } @@ -2760,6 +2836,137 @@ namespace MediaBrowser.Server.Implementations.Library } } + private bool ValidateNetworkPath(string path) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT || !path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) + { + return Directory.Exists(path); + } + + // Without native support for unc, we cannot validate this when running under mono + return true; + } + + private const string ShortcutFileExtension = ".mblink"; + private const string ShortcutFileSearch = "*" + ShortcutFileExtension; + public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + { + AddMediaPathInternal(virtualFolderName, pathInfo, true); + } + + private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) + { + if (pathInfo == null) + { + throw new ArgumentNullException("path"); + } + + var path = pathInfo.Path; + + if (string.IsNullOrWhiteSpace(path)) + { + throw new ArgumentNullException("path"); + } + + if (!_fileSystem.DirectoryExists(path)) + { + throw new DirectoryNotFoundException("The path does not exist."); + } + + if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath)) + { + throw new DirectoryNotFoundException("The network path does not exist."); + } + + var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); + + var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); + + var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); + + while (_fileSystem.FileExists(lnk)) + { + shortcutFilename += "1"; + lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); + } + + _fileSystem.CreateShortcut(lnk, path); + + RemoveContentTypeOverrides(path); + + if (saveLibraryOptions) + { + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + var list = libraryOptions.PathInfos.ToList(); + list.Add(pathInfo); + libraryOptions.PathInfos = list.ToArray(); + + SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); + } + } + + public void UpdateMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + { + if (pathInfo == null) + { + throw new ArgumentNullException("path"); + } + + if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath)) + { + throw new DirectoryNotFoundException("The network path does not exist."); + } + + var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); + + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions); + + var list = libraryOptions.PathInfos.ToList(); + foreach (var originalPathInfo in list) + { + if (string.Equals(pathInfo.Path, originalPathInfo.Path, StringComparison.Ordinal)) + { + originalPathInfo.NetworkPath = pathInfo.NetworkPath; + break; + } + } + + libraryOptions.PathInfos = list.ToArray(); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); + } + + private void SyncLibraryOptionsToLocations(string virtualFolderPath, LibraryOptions options) + { + var topLibraryFolders = GetUserRootFolder().Children.ToList(); + var info = GetVirtualFolderInfo(virtualFolderPath, topLibraryFolders); + + if (info.Locations.Count > 0 && info.Locations.Count != options.PathInfos.Length) + { + var list = options.PathInfos.ToList(); + + foreach (var location in info.Locations) + { + if (!list.Any(i => string.Equals(i.Path, location, StringComparison.Ordinal))) + { + list.Add(new MediaPathInfo + { + Path = location + }); + } + } + + options.PathInfos = list.ToArray(); + } + } + public void RemoveVirtualFolder(string name, bool refreshLibrary) { if (string.IsNullOrWhiteSpace(name)) @@ -2804,38 +3011,6 @@ namespace MediaBrowser.Server.Implementations.Library } } - private const string ShortcutFileExtension = ".mblink"; - private const string ShortcutFileSearch = "*" + ShortcutFileExtension; - public void AddMediaPath(string virtualFolderName, string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - if (!_fileSystem.DirectoryExists(path)) - { - throw new DirectoryNotFoundException("The path does not exist."); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - - var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); - - var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - - while (_fileSystem.FileExists(lnk)) - { - shortcutFilename += "1"; - lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - } - - _fileSystem.CreateShortcut(lnk, path); - - RemoveContentTypeOverrides(path); - } - private void RemoveContentTypeOverrides(string path) { if (string.IsNullOrWhiteSpace(path)) @@ -2872,19 +3047,28 @@ namespace MediaBrowser.Server.Implementations.Library } var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var path = Path.Combine(rootFolderPath, virtualFolderName); + var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - if (!_fileSystem.DirectoryExists(path)) + if (!_fileSystem.DirectoryExists(virtualFolderPath)) { throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName)); } - var shortcut = Directory.EnumerateFiles(path, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => _fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase)); + var shortcut = Directory.EnumerateFiles(virtualFolderPath, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => _fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(shortcut)) { _fileSystem.DeleteFile(shortcut); } + + var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); + + libraryOptions.PathInfos = libraryOptions + .PathInfos + .Where(i => !string.Equals(i.Path, mediaPath, StringComparison.Ordinal)) + .ToArray(); + + CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 4a533ff93..e7bfe56f2 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -221,8 +221,28 @@ namespace MediaBrowser.Server.Implementations.Library } } - public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution) + public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken) { + if (!string.IsNullOrWhiteSpace(liveStreamId)) + { + return await GetLiveStream(liveStreamId, cancellationToken).ConfigureAwait(false); + } + //await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + + //try + //{ + // var stream = _openStreams.Values.FirstOrDefault(i => string.Equals(i.MediaSource.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); + + // if (stream != null) + // { + // return stream.MediaSource; + // } + //} + //finally + //{ + // _liveStreamSemaphore.Release(); + //} + var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video }, CancellationToken.None).ConfigureAwait(false); @@ -335,7 +355,7 @@ namespace MediaBrowser.Server.Implementations.Library .ToList(); } - private readonly ConcurrentDictionary<string, LiveStreamInfo> _openStreams = new ConcurrentDictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary<string, LiveStreamInfo> _openStreams = new Dictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) @@ -347,7 +367,9 @@ namespace MediaBrowser.Server.Implementations.Library var tuple = GetProvider(request.OpenToken); var provider = tuple.Item1; - var mediaSource = await provider.OpenMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false); + var mediaSourceTuple = await provider.OpenMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false); + + var mediaSource = mediaSourceTuple.Item1; if (string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) { @@ -361,9 +383,11 @@ namespace MediaBrowser.Server.Implementations.Library Date = DateTime.UtcNow, EnableCloseTimer = enableAutoClose, Id = mediaSource.LiveStreamId, - MediaSource = mediaSource + MediaSource = mediaSource, + DirectStreamProvider = mediaSourceTuple.Item2 }; - _openStreams.AddOrUpdate(mediaSource.LiveStreamId, info, (key, i) => info); + + _openStreams[mediaSource.LiveStreamId] = info; if (enableAutoClose) { @@ -394,14 +418,14 @@ namespace MediaBrowser.Server.Implementations.Library } } - public async Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken) + public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(id)) { throw new ArgumentNullException("id"); } - _logger.Debug("Getting live stream {0}", id); + _logger.Debug("Getting already opened live stream {0}", id); await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -410,7 +434,7 @@ namespace MediaBrowser.Server.Implementations.Library LiveStreamInfo info; if (_openStreams.TryGetValue(id, out info)) { - return info.MediaSource; + return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info.DirectStreamProvider); } else { @@ -423,6 +447,12 @@ namespace MediaBrowser.Server.Implementations.Library } } + public async Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken) + { + var result = await GetLiveStreamWithDirectStreamProvider(id, cancellationToken).ConfigureAwait(false); + return result.Item1; + } + public async Task PingLiveStream(string id, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -436,7 +466,7 @@ namespace MediaBrowser.Server.Implementations.Library } else { - _logger.Error("Failed to update MediaSource timestamp for {0}", id); + _logger.Error("Failed to ping live stream {0}", id); } } finally @@ -445,17 +475,16 @@ namespace MediaBrowser.Server.Implementations.Library } } - private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId, CancellationToken cancellationToken) + private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId) { _logger.Info("Closing live stream {0} with provider {1}", streamId, provider.GetType().Name); try { - await provider.CloseMediaSource(streamId, cancellationToken).ConfigureAwait(false); + await provider.CloseMediaSource(streamId).ConfigureAwait(false); } catch (NotImplementedException) { - } catch (Exception ex) { @@ -463,37 +492,35 @@ namespace MediaBrowser.Server.Implementations.Library } } - public async Task CloseLiveStream(string id, CancellationToken cancellationToken) + public async Task CloseLiveStream(string id) { if (string.IsNullOrWhiteSpace(id)) { throw new ArgumentNullException("id"); } - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false); try { LiveStreamInfo current; + if (_openStreams.TryGetValue(id, out current)) { + _openStreams.Remove(id); + current.Closed = true; + if (current.MediaSource.RequiresClosing) { var tuple = GetProvider(id); - await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false); + await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2).ConfigureAwait(false); } - } - LiveStreamInfo removed; - if (_openStreams.TryRemove(id, out removed)) - { - removed.Closed = true; - } - - if (_openStreams.Count == 0) - { - StopCloseTimer(); + if (_openStreams.Count == 0) + { + StopCloseTimer(); + } } } finally @@ -523,7 +550,7 @@ namespace MediaBrowser.Server.Implementations.Library } private Timer _closeTimer; - private readonly TimeSpan _openStreamMaxAge = TimeSpan.FromSeconds(60); + private readonly TimeSpan _openStreamMaxAge = TimeSpan.FromSeconds(180); private void StartCloseTimer() { @@ -545,10 +572,20 @@ namespace MediaBrowser.Server.Implementations.Library private async void CloseTimerCallback(object state) { - var infos = _openStreams - .Values - .Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge) - .ToList(); + List<LiveStreamInfo> infos; + await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false); + + try + { + infos = _openStreams + .Values + .Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge) + .ToList(); + } + finally + { + _liveStreamSemaphore.Release(); + } foreach (var info in infos) { @@ -556,7 +593,7 @@ namespace MediaBrowser.Server.Implementations.Library { try { - await CloseLiveStream(info.Id, CancellationToken.None).ConfigureAwait(false); + await CloseLiveStream(info.Id).ConfigureAwait(false); } catch (Exception ex) { @@ -588,12 +625,10 @@ namespace MediaBrowser.Server.Implementations.Library { foreach (var key in _openStreams.Keys.ToList()) { - var task = CloseLiveStream(key, CancellationToken.None); + var task = CloseLiveStream(key); Task.WaitAll(task); } - - _openStreams.Clear(); } } } @@ -605,6 +640,7 @@ namespace MediaBrowser.Server.Implementations.Library public string Id; public bool Closed; public MediaSourceInfo MediaSource; + public IDirectStreamProvider DirectStreamProvider; } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 1a8295800..7f35fc3ea 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -54,8 +54,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio if (!args.IsDirectory) return null; // Avoid mis-identifying top folders - if (args.Parent.IsRoot) return null; if (args.HasParent<MusicAlbum>()) return null; + if (args.Parent.IsRoot) return null; var collectionType = args.GetCollectionType(); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index e819af06f..686105ddb 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -7,6 +7,7 @@ using System; using System.IO; using System.Linq; using CommonIO; +using MediaBrowser.Controller.Configuration; namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio { @@ -18,12 +19,14 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _config; - public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager) + public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config) { _logger = logger; _fileSystem = fileSystem; _libraryManager = libraryManager; + _config = config; } /// <summary> @@ -48,9 +51,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio { if (!args.IsDirectory) return null; - // Avoid mis-identifying top folders - if (args.Parent.IsRoot) return null; - // Don't allow nested artists if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>()) { @@ -67,6 +67,19 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio return null; } + if (args.ContainsFileSystemEntryByName("artist.nfo")) + { + return new MusicArtist(); + } + + if (_config.Configuration.EnableSimpleArtistDetection) + { + return null; + } + + // Avoid mis-identifying top folders + if (args.Parent.IsRoot) return null; + var directoryService = args.DirectoryService; var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs index 34237622d..ff07c5282 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs @@ -51,7 +51,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers base.SetInitialItemValues(item, args); item.IsRoot = args.Parent == null; - item.IsPhysicalRoot = args.IsPhysicalRoot; } } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index ee9533d2a..c3d5f3441 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -48,12 +48,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies string collectionType, IDirectoryService directoryService) { - if (parent != null && parent.Path != null && parent.Path.IndexOf("disney", StringComparison.OrdinalIgnoreCase) != -1) - { - var b = true; - var a = b; - } - var result = ResolveMultipleInternal(parent, files, collectionType, directoryService); if (result != null) @@ -213,26 +207,22 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies // Find movies with their own folders if (args.IsDirectory) { - var files = args.FileSystemChildren - .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) - .ToList(); - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie<MusicVideo>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + return null; } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + return null; } if (string.IsNullOrEmpty(collectionType)) { - // Owned items should just use the plain video type + // Owned items will be caught by the plain video resolver if (args.Parent == null) { - return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + return null; } if (args.HasParent<Series>()) @@ -240,11 +230,21 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies return null; } - return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + { + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + + return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + } } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType); } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 4c6254330..c82825007 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -54,11 +54,20 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV { if (args.IsDirectory) { - if (args.HasParent<Series>()) + if (args.HasParent<Series>() || args.HasParent<Season>()) { return null; } + if (args.ContainsFileSystemEntryByName("tvshow.nfo")) + { + return new Series + { + Path = args.Path, + Name = Path.GetFileName(args.Path) + }; + } + var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { @@ -72,22 +81,20 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV }; } } - else + else if (string.IsNullOrWhiteSpace(collectionType)) { - if (string.IsNullOrWhiteSpace(collectionType)) + if (args.Parent.IsRoot) { - if (args.Parent.IsRoot) - { - return null; - } - if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false)) + return null; + } + + if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false)) + { + return new Series { - return new Series - { - Path = args.Path, - Name = Path.GetFileName(args.Path) - }; - } + Path = args.Path, + Name = Path.GetFileName(args.Path) + }; } } } diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index a6d6b5cb8..40cca7bab 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -105,6 +105,7 @@ namespace MediaBrowser.Server.Implementations.Library var includeItemTypes = (query.IncludeItemTypes ?? new string[] { }).ToList(); excludeItemTypes.Add(typeof(Year).Name); + excludeItemTypes.Add(typeof(Folder).Name); if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase))) { diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index 307cf4cd2..9ee65a57c 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -61,16 +61,7 @@ namespace MediaBrowser.Server.Implementations.Library foreach (var key in keys) { - try - { - await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving user data", ex); - - throw; - } + await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); } var cacheKey = GetCacheKey(userId, item.Id); @@ -107,18 +98,7 @@ namespace MediaBrowser.Server.Implementations.Library cancellationToken.ThrowIfCancellationRequested(); - try - { - await Repository.SaveAllUserData(userId, userData, cancellationToken).ConfigureAwait(false); - - } - catch (Exception ex) - { - _logger.ErrorException("Error saving user data", ex); - - throw; - } - + await Repository.SaveAllUserData(userId, userData, cancellationToken).ConfigureAwait(false); } /// <summary> @@ -289,6 +269,11 @@ namespace MediaBrowser.Server.Implementations.Library positionTicks = 0; } + if (!item.SupportsPlayedStatus) + { + positionTicks = 0; + data.Played = false; + } if (item is Audio) { positionTicks = 0; |
