Merge pull request #2224 from MediaBrowser/beta

Beta
This commit is contained in:
Luke
2016-10-12 15:43:28 -04:00
committed by GitHub
337 changed files with 10368 additions and 6073 deletions

View File

@@ -33,7 +33,8 @@ namespace MediaBrowser.Server.Implementations.Library
// Synology
"@eaDir",
"eaDir"
"eaDir",
"#recycle"
};

View File

@@ -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();
}
return collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions();
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;
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,7 +2544,59 @@ 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))
{
@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -51,7 +51,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
base.SetInitialItemValues(item, args);
item.IsRoot = args.Parent == null;
item.IsPhysicalRoot = args.IsPhysicalRoot;
}
}
}

View File

@@ -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);
}

View File

@@ -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 new Series
{
return null;
}
if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false))
{
return new Series
{
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
}
}

View File

@@ -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)))
{

View File

@@ -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;