aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Library
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/Library')
-rw-r--r--MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs324
-rw-r--r--MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs104
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs30
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs35
-rw-r--r--MediaBrowser.Server.Implementations/Library/SearchEngine.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserDataManager.cs29
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;