diff options
Diffstat (limited to 'MediaBrowser.Api')
35 files changed, 190 insertions, 247 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index c2b406190f..aa5cd8d5f8 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.Api { var path = _config.ApplicationPaths.TranscodingTempPath; - foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) + foreach (var file in _fileSystem.GetFilePaths(path, true) .ToList()) { _fileSystem.DeleteFile(file); @@ -567,7 +567,7 @@ namespace MediaBrowser.Api var directory = Path.GetDirectoryName(outputFilePath); var name = Path.GetFileNameWithoutExtension(outputFilePath); - var filesToDelete = Directory.EnumerateFiles(directory) + var filesToDelete = _fileSystem.GetFilePaths(directory) .Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1) .ToList(); diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs deleted file mode 100644 index 87084e415a..0000000000 --- a/MediaBrowser.Api/AppThemeService.cs +++ /dev/null @@ -1,100 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Themes; -using MediaBrowser.Model.Themes; -using ServiceStack; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Api -{ - [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")] - public class GetAppThemes : IReturn<List<AppThemeInfo>> - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - } - - [Route("/Themes/Info", "GET", Summary = "Gets an app theme")] - public class GetAppTheme : IReturn<AppTheme> - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - - [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Name { get; set; } - } - - [Route("/Themes/Images", "GET", Summary = "Gets an app theme")] - public class GetAppThemeImage - { - [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string App { get; set; } - - [ApiMember(Name = "Theme", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Theme { get; set; } - - [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Name { get; set; } - - [ApiMember(Name = "CacheTag", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string CacheTag { get; set; } - } - - [Route("/Themes", "POST", Summary = "Saves a theme")] - public class SaveTheme : AppTheme, IReturnVoid - { - } - - [Authenticated] - public class AppThemeService : BaseApiService - { - private readonly IAppThemeManager _themeManager; - private readonly IFileSystem _fileSystem; - - public AppThemeService(IAppThemeManager themeManager, IFileSystem fileSystem) - { - _themeManager = themeManager; - _fileSystem = fileSystem; - } - - public object Get(GetAppThemes request) - { - var result = _themeManager.GetThemes(request.App).ToList(); - - return ToOptimizedResult(result); - } - - public object Get(GetAppTheme request) - { - var result = _themeManager.GetTheme(request.App, request.Name); - - return ToOptimizedResult(result); - } - - public void Post(SaveTheme request) - { - _themeManager.SaveTheme(request); - } - - public object Get(GetAppThemeImage request) - { - var info = _themeManager.GetImageImageInfo(request.App, request.Theme, request.Name); - - var cacheGuid = new Guid(info.CacheTag); - - TimeSpan? cacheDuration = null; - - if (!string.IsNullOrEmpty(request.CacheTag) && cacheGuid == new Guid(request.CacheTag)) - { - cacheDuration = TimeSpan.FromDays(365); - } - - var contentType = MimeTypes.GetMimeType(info.Path); - - return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType); - } - } -} diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs index 4f5e2ab259..4e7b1a7d58 100644 --- a/MediaBrowser.Api/Dlna/DlnaServerService.cs +++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs @@ -108,7 +108,6 @@ namespace MediaBrowser.Api.Dlna private readonly IConnectionManager _connectionManager; private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar; - // TODO: Add utf-8 private const string XMLContentType = "text/xml; charset=UTF-8"; public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar) diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 457b4709bf..81b326da8f 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; @@ -96,13 +97,14 @@ namespace MediaBrowser.Api /// The _network manager /// </summary> private readonly INetworkManager _networkManager; + private IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="EnvironmentService" /> class. /// </summary> /// <param name="networkManager">The network manager.</param> /// <exception cref="System.ArgumentNullException">networkManager</exception> - public EnvironmentService(INetworkManager networkManager) + public EnvironmentService(INetworkManager networkManager, IFileSystem fileSystem) { if (networkManager == null) { @@ -110,6 +112,7 @@ namespace MediaBrowser.Api } _networkManager = networkManager; + _fileSystem = fileSystem; } /// <summary> @@ -117,8 +120,6 @@ namespace MediaBrowser.Api /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">Path</exception> - /// <exception cref="System.ArgumentException"></exception> public object Get(GetDirectoryContents request) { var path = request.Path; @@ -222,8 +223,7 @@ namespace MediaBrowser.Api private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request) { // using EnumerateFileSystemInfos doesn't handle reparse points (symlinks) - var entries = new DirectoryInfo(request.Path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly) - .Concat<FileSystemInfo>(new DirectoryInfo(request.Path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)).Where(i => + var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i => { if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden)) { diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs index b4d5a99497..a6e1af516c 100644 --- a/MediaBrowser.Api/Images/ImageByNameService.cs +++ b/MediaBrowser.Api/Images/ImageByNameService.cs @@ -130,8 +130,7 @@ namespace MediaBrowser.Api.Images { try { - return new DirectoryInfo(path) - .GetFiles("*", SearchOption.AllDirectories) + return _fileSystem.GetFiles(path) .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal)) .Select(i => new ImageByNameInfo { @@ -184,7 +183,7 @@ namespace MediaBrowser.Api.Images var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList(); - var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault(); + var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault(); return ToStaticFileResult(path); } @@ -198,11 +197,11 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme); - if (Directory.Exists(themeFolder)) + if (_fileSystem.DirectoryExists(themeFolder)) { var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -212,14 +211,14 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.RatingsPath, "all"); - if (Directory.Exists(allFolder)) + if (_fileSystem.DirectoryExists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -239,10 +238,10 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme); - if (Directory.Exists(themeFolder)) + if (_fileSystem.DirectoryExists(themeFolder)) { var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { @@ -252,13 +251,13 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all"); - if (Directory.Exists(allFolder)) + if (_fileSystem.DirectoryExists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(File.Exists); + .FirstOrDefault(_fileSystem.FileExists); if (!string.IsNullOrEmpty(path)) { diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 6d2579ea9f..c67ef96c96 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -237,7 +237,7 @@ namespace MediaBrowser.Api.Images contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (File.Exists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -281,7 +281,7 @@ namespace MediaBrowser.Api.Images var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -290,7 +290,7 @@ namespace MediaBrowser.Api.Images } } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index a0ba6e61f8..9f7f57155b 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -200,7 +200,7 @@ namespace MediaBrowser.Api //} item.ProviderIds = request.ProviderIds; - var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions + var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) { MetadataRefreshMode = MetadataRefreshMode.FullRefresh, ImageRefreshMode = ImageRefreshMode.FullRefresh, @@ -230,7 +230,7 @@ namespace MediaBrowser.Api contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (File.Exists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -271,7 +271,7 @@ namespace MediaBrowser.Api var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -280,7 +280,7 @@ namespace MediaBrowser.Api } } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index f56fd32828..1e74b36923 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using ServiceStack; using System.Threading; +using MediaBrowser.Common.IO; namespace MediaBrowser.Api { @@ -37,11 +38,13 @@ namespace MediaBrowser.Api { private readonly ILibraryManager _libraryManager; private readonly IProviderManager _providerManager; + private readonly IFileSystem _fileSystem; - public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager) + public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager, IFileSystem fileSystem) { _libraryManager = libraryManager; _providerManager = providerManager; + _fileSystem = fileSystem; } /// <summary> @@ -66,7 +69,7 @@ namespace MediaBrowser.Api private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request) { - return new MetadataRefreshOptions(new DirectoryService()) + return new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { MetadataRefreshMode = request.MetadataRefreshMode, ImageRefreshMode = request.ImageRefreshMode, diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index b8ae9392ae..23ff744957 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -211,11 +211,6 @@ namespace MediaBrowser.Api UpdateItem(request, item); - if (isLockedChanged && item.IsLocked) - { - item.IsUnidentified = false; - } - await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (request.People != null) @@ -321,13 +316,8 @@ namespace MediaBrowser.Api SetProductionLocations(item, request); - var hasLang = item as IHasPreferredMetadataLanguage; - - if (hasLang != null) - { - hasLang.PreferredMetadataCountryCode = request.PreferredMetadataCountryCode; - hasLang.PreferredMetadataLanguage = request.PreferredMetadataLanguage; - } + item.PreferredMetadataCountryCode = request.PreferredMetadataCountryCode; + item.PreferredMetadataLanguage = request.PreferredMetadataLanguage; var hasDisplayOrder = item as IHasDisplayOrder; if (hasDisplayOrder != null) diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs index 0ee28d6fef..877321b777 100644 --- a/MediaBrowser.Api/Library/LibraryHelpers.cs +++ b/MediaBrowser.Api/Library/LibraryHelpers.cs @@ -33,11 +33,11 @@ namespace MediaBrowser.Api.Library var rootFolderPath = appPaths.DefaultUserViewsPath; var path = Path.Combine(rootFolderPath, virtualFolderName); - if (!Directory.Exists(path)) + if (!fileSystem.DirectoryExists(path)) { 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)); if (!string.IsNullOrEmpty(shortcut)) @@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Library /// <exception cref="System.ArgumentException">The path is not valid.</exception> public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, IServerApplicationPaths appPaths) { - if (!Directory.Exists(path)) + if (!fileSystem.DirectoryExists(path)) { throw new DirectoryNotFoundException("The path does not exist."); } @@ -69,7 +69,7 @@ namespace MediaBrowser.Api.Library var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - while (File.Exists(lnk)) + while (fileSystem.FileExists(lnk)) { shortcutFilename += "1"; lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 49dd121baa..20fd1ef40a 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -27,6 +27,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.IO; namespace MediaBrowser.Api.Library { @@ -282,12 +283,13 @@ namespace MediaBrowser.Api.Library private readonly IChannelManager _channelManager; private readonly ITVSeriesManager _tvManager; private readonly ILibraryMonitor _libraryMonitor; + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="LibraryService" /> class. /// </summary> public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, - IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor) + IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem) { _itemRepo = itemRepo; _libraryManager = libraryManager; @@ -301,6 +303,7 @@ namespace MediaBrowser.Api.Library _channelManager = channelManager; _tvManager = tvManager; _libraryMonitor = libraryMonitor; + _fileSystem = fileSystem; } public object Get(GetSimilarItems request) @@ -557,7 +560,7 @@ namespace MediaBrowser.Api.Library { throw new ArgumentException("This command cannot be used for remote or virtual items."); } - if (Directory.Exists(item.Path)) + if (_fileSystem.DirectoryExists(item.Path)) { throw new ArgumentException("This command cannot be used for directories."); } @@ -719,7 +722,7 @@ namespace MediaBrowser.Api.Library if (!item.CanDelete(user)) { - throw new UnauthorizedAccessException(); + throw new SecurityException("Unauthorized access"); } if (item is ILiveTvRecording) diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index f5fe921cec..c8731637c3 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.Api.Library var virtualFolderPath = Path.Combine(rootFolderPath, name); - if (Directory.Exists(virtualFolderPath)) + if (_fileSystem.DirectoryExists(virtualFolderPath)) { throw new ArgumentException("There is already a media collection with the name " + name + "."); } @@ -204,13 +204,16 @@ namespace MediaBrowser.Api.Library try { - Directory.CreateDirectory(virtualFolderPath); + _fileSystem.CreateDirectory(virtualFolderPath); if (!string.IsNullOrEmpty(request.CollectionType)) { var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection"); - File.Create(path); + using (File.Create(path)) + { + + } } } finally @@ -256,12 +259,12 @@ namespace MediaBrowser.Api.Library var currentPath = Path.Combine(rootFolderPath, request.Name); var newPath = Path.Combine(rootFolderPath, request.NewName); - if (!Directory.Exists(currentPath)) + if (!_fileSystem.DirectoryExists(currentPath)) { throw new DirectoryNotFoundException("The media collection does not exist"); } - if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath)) + if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath)) { throw new ArgumentException("There is already a media collection with the name " + newPath + "."); } @@ -276,11 +279,11 @@ namespace MediaBrowser.Api.Library //Create an unique name var temporaryName = Guid.NewGuid().ToString(); var temporaryPath = Path.Combine(rootFolderPath, temporaryName); - Directory.Move(currentPath, temporaryPath); + _fileSystem.MoveDirectory(currentPath, temporaryPath); currentPath = temporaryPath; } - Directory.Move(currentPath, newPath); + _fileSystem.MoveDirectory(currentPath, newPath); } finally { @@ -319,7 +322,7 @@ namespace MediaBrowser.Api.Library var path = Path.Combine(rootFolderPath, request.Name); - if (!Directory.Exists(path)) + if (!_fileSystem.DirectoryExists(path)) { throw new DirectoryNotFoundException("The media folder does not exist"); } diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 07e64c98d4..344d6ab3d3 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -521,12 +521,12 @@ namespace MediaBrowser.Api.LiveTv if (user == null) { - throw new UnauthorizedAccessException("Anonymous live tv management is not allowed."); + throw new SecurityException("Anonymous live tv management is not allowed."); } if (!user.Policy.EnableLiveTvManagement) { - throw new UnauthorizedAccessException("The current user does not have permission to manage live tv."); + throw new SecurityException("The current user does not have permission to manage live tv."); } } diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 295cc78e93..901dd11e2a 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -11,10 +11,10 @@ <AssemblyName>MediaBrowser.Api</AssemblyName> <FileAlignment>512</FileAlignment> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <ProductVersion>10.0.0</ProductVersion> - <SchemaVersion>2.0</SchemaVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <RestorePackages>true</RestorePackages> + <ReleaseVersion> + </ReleaseVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> @@ -25,7 +25,6 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <PlatformTarget>AnyCPU</PlatformTarget> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>none</DebugType> @@ -34,7 +33,6 @@ <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' "> <DebugType>none</DebugType> @@ -43,16 +41,11 @@ <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup> <RunPostBuildEvent>Always</RunPostBuildEvent> </PropertyGroup> <ItemGroup> - <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath> - </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="Microsoft.CSharp" /> @@ -64,12 +57,14 @@ <Reference Include="ServiceStack.Text"> <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath> </Reference> + <Reference Include="MoreLinq"> + <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> - <Compile Include="AppThemeService.cs" /> <Compile Include="BrandingService.cs" /> <Compile Include="ChannelService.cs" /> <Compile Include="ConnectService.cs" /> diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 531d67eedd..8e5061d62a 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -290,13 +290,6 @@ namespace MediaBrowser.Api.Playback { get { - var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder; - - if (!string.IsNullOrWhiteSpace(lib)) - { - return lib; - } - return "libx264"; } } @@ -810,13 +803,53 @@ namespace MediaBrowser.Api.Playback } /// <summary> + /// Gets the name of the output video codec + /// </summary> + /// <param name="state">The state.</param> + /// <returns>System.String.</returns> + protected string GetVideoDecoder(StreamState state) + { + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase)) + { + if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + { + switch (state.MediaSource.VideoStream.Codec.ToLower()) + { + case "avc": + case "h264": + if (MediaEncoder.SupportsDecoder("h264_qsv")) + { + return "-c:v h264_qsv "; + } + break; + case "mpeg2video": + if (MediaEncoder.SupportsDecoder("mpeg2_qsv")) + { + return "-c:v mpeg2_qsv "; + } + break; + case "vc1": + if (MediaEncoder.SupportsDecoder("vc1_qsv")) + { + return "-c:v vc1_qsv "; + } + break; + } + } + } + + // leave blank so ffmpeg will decide + return null; + } + + /// <summary> /// Gets the input argument. /// </summary> /// <param name="state">The state.</param> /// <returns>System.String.</returns> protected string GetInputArgument(StreamState state) { - var arg = "-i " + GetInputPathArgument(state); + var arg = string.Format("-i {0}", GetInputPathArgument(state)); if (state.SubtitleStream != null) { @@ -826,7 +859,7 @@ namespace MediaBrowser.Api.Playback } } - return arg; + return arg.Trim(); } private string GetInputPathArgument(StreamState state) @@ -840,7 +873,7 @@ namespace MediaBrowser.Api.Playback { if (!(state.VideoType == VideoType.Iso && state.IsoMount == null)) { - inputPath = MediaEncoderHelpers.GetInputArgument(mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); + inputPath = MediaEncoderHelpers.GetInputArgument(FileSystem, mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); } } @@ -889,7 +922,7 @@ namespace MediaBrowser.Api.Playback CancellationTokenSource cancellationTokenSource, string workingDirectory = null) { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); @@ -942,7 +975,7 @@ namespace MediaBrowser.Api.Playback Logger.Info(commandLineLogMessage); var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt"); - Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); + FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); @@ -972,7 +1005,7 @@ namespace MediaBrowser.Api.Playback StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream); // Wait for the file to exist before proceeeding - while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) + while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) { await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } @@ -1027,6 +1060,7 @@ namespace MediaBrowser.Api.Playback var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await target.FlushAsync().ConfigureAwait(false); } } } @@ -2158,6 +2192,12 @@ namespace MediaBrowser.Api.Playback inputModifier += " -re"; } + var videoDecoder = GetVideoDecoder(state); + if (!string.IsNullOrWhiteSpace(videoDecoder)) + { + inputModifier += " " + videoDecoder; + } + return inputModifier; } diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs index c201ffd587..cbee821d2d 100644 --- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Dash var workingDirectory = Path.Combine(Path.GetDirectoryName(playlistPath), (startNumber == -1 ? 0 : startNumber).ToString(CultureInfo.InvariantCulture)); state.WaitForPath = Path.Combine(workingDirectory, Path.GetFileName(playlistPath)); - Directory.CreateDirectory(workingDirectory); + FileSystem.CreateDirectory(workingDirectory); job = await StartFfMpeg(state, playlistPath, cancellationTokenSource, workingDirectory).ConfigureAwait(false); await WaitForMinimumDashSegmentCount(Path.Combine(workingDirectory, Path.GetFileName(playlistPath)), 1, cancellationTokenSource.Token).ConfigureAwait(false); } @@ -328,8 +328,7 @@ namespace MediaBrowser.Api.Playback.Dash try { - return new DirectoryInfo(folder) - .EnumerateFiles("*", SearchOption.AllDirectories) + return fileSystem.GetFiles(folder) .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(fileSystem.GetLastWriteTimeUtc) .Take(count) @@ -348,20 +347,20 @@ namespace MediaBrowser.Api.Playback.Dash if (requestedIndex == -1) { var path = Path.Combine(folder, "0", "stream" + representationId + "-" + "init" + segmentExtension); - return File.Exists(path) ? path : null; + return FileSystem.FileExists(path) ? path : null; } try { - foreach (var subfolder in new DirectoryInfo(folder).EnumerateDirectories().ToList()) + foreach (var subfolder in FileSystem.GetDirectoryPaths(folder).ToList()) { - var subfolderName = Path.GetFileNameWithoutExtension(subfolder.FullName); + var subfolderName = Path.GetFileNameWithoutExtension(subfolder); int startNumber; if (int.TryParse(subfolderName, NumberStyles.Any, UsCulture, out startNumber)) { var segmentIndex = requestedIndex - startNumber + 1; var path = Path.Combine(folder, subfolderName, "stream" + representationId + "-" + segmentIndex.ToString("00000", CultureInfo.InvariantCulture) + segmentExtension); - if (File.Exists(path)) + if (FileSystem.FileExists(path)) { return path; } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index e4f00e2a08..a9a9610a97 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -23,7 +23,8 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) + protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) + : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { } @@ -90,12 +91,12 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; var playlist = state.OutputFilePath; - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { // If the playlist doesn't already exist, startup ffmpeg try @@ -150,7 +151,7 @@ namespace MediaBrowser.Api.Playback.Hls { ApiEntryPoint.Instance.OnTranscodeEndRequest(job); } - + return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>()); } @@ -317,4 +318,4 @@ namespace MediaBrowser.Api.Playback.Hls return false; } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7b2844cd4b..cb49e65c7e 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -165,7 +165,7 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -386,8 +386,7 @@ namespace MediaBrowser.Api.Playback.Hls try { - return new DirectoryInfo(folder) - .EnumerateFiles("*", SearchOption.TopDirectoryOnly) + return fileSystem.GetFiles(folder) .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase) && Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(fileSystem.GetLastWriteTimeUtc) .FirstOrDefault(); @@ -432,7 +431,7 @@ namespace MediaBrowser.Api.Playback.Hls CancellationToken cancellationToken) { // If all transcoding has completed, just return immediately - if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath)) + if (transcodingJob != null && transcodingJob.HasExited && FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } @@ -452,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls // If it appears in the playlist, it's done if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } @@ -989,4 +988,4 @@ namespace MediaBrowser.Api.Playback.Hls return base.CanStreamCopyVideo(request, videoStream); } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 0b7b501340..2ab2d11f60 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Playback Size = 102400; } } - + [Authenticated] public class MediaInfoService : BaseApiService { @@ -289,7 +289,7 @@ namespace MediaBrowser.Api.Playback if (mediaSource.SupportsDirectStream) { options.MaxBitrate = GetMaxBitrate(maxBitrate); - + // The MediaSource supports direct stream, now test to see if the client supports it var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? streamBuilder.BuildAudioItem(options) : @@ -309,7 +309,7 @@ namespace MediaBrowser.Api.Playback if (mediaSource.SupportsTranscoding) { options.MaxBitrate = GetMaxBitrate(maxBitrate); - + // The MediaSource supports direct stream, now test to see if the client supports it var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? streamBuilder.BuildAudioItem(options) : @@ -336,9 +336,15 @@ namespace MediaBrowser.Api.Playback var maxBitrate = clientMaxBitrate; var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit; - if (remoteClientMaxBitrate > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp)) + if (remoteClientMaxBitrate > 0) { - maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate); + var isInLocalNetwork = _networkManager.IsInLocalNetwork(Request.RemoteIp); + + Logger.Info("RemoteClientBitrateLimit: {0}, RemoteIp: {1}, IsInLocalNetwork: {2}", remoteClientMaxBitrate, Request.RemoteIp, isInLocalNetwork); + if (!isInLocalNetwork) + { + maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate); + } } return maxBitrate; diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 910ac18e7b..aa0cda133b 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive } var outputPath = state.OutputFilePath; - var outputPathExists = File.Exists(outputPath); + var outputPathExists = FileSystem.FileExists(outputPath); var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive); @@ -325,7 +325,7 @@ namespace MediaBrowser.Api.Playback.Progressive { TranscodingJob job; - if (!File.Exists(outputPath)) + if (!FileSystem.FileExists(outputPath)) { job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 84ae26248f..1dfb433879 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -17,6 +17,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// <summary> /// Class GetVideoStream /// </summary> + [Route("/Videos/{Id}/stream.mpegts", "GET")] [Route("/Videos/{Id}/stream.ts", "GET")] [Route("/Videos/{Id}/stream.webm", "GET")] [Route("/Videos/{Id}/stream.asf", "GET")] diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 34dc5ea12f..fdbe5835ef 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Api.Playback { get { - return ReadInputAtNativeFramerate ? 1000 : 0; + return 0; } } diff --git a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs index af5abf46aa..62f941a7a0 100644 --- a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs +++ b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs @@ -43,7 +43,6 @@ namespace MediaBrowser.Api.Reports MusicArtist, AudioAlbum, Locked, - Unidentified, ImagePrimary, ImageBackdrop, ImageLogo, diff --git a/MediaBrowser.Api/Reports/Common/ItemViewType.cs b/MediaBrowser.Api/Reports/Common/ItemViewType.cs index 5126457cf9..0984421153 100644 --- a/MediaBrowser.Api/Reports/Common/ItemViewType.cs +++ b/MediaBrowser.Api/Reports/Common/ItemViewType.cs @@ -17,7 +17,6 @@ namespace MediaBrowser.Api.Reports TrailersImage, SpecialsImage, LockDataImage, - UnidentifiedImage, TagsPrimaryImage, TagsBackdropImage, TagsLogoImage, diff --git a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs index 512441bd7b..5e339dc734 100644 --- a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs +++ b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs @@ -105,7 +105,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -122,7 +121,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -143,7 +141,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -161,7 +158,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -177,7 +173,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -198,7 +193,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -223,7 +217,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -241,7 +234,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -260,7 +252,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -284,7 +275,6 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -315,11 +305,9 @@ namespace MediaBrowser.Api.Reports { HeaderMetadata.Status, HeaderMetadata.Locked, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, - HeaderMetadata.Unidentified, HeaderMetadata.ImagePrimary, HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageLogo, @@ -376,12 +364,6 @@ namespace MediaBrowser.Api.Reports option.Header.CanGroup = false; option.Header.DisplayType = ReportDisplayType.Export; break; - case HeaderMetadata.Unidentified: - option.Column = (i, r) => this.GetBoolString(r.IsUnidentified); - option.Header.ItemViewType = ItemViewType.UnidentifiedImage; - option.Header.CanGroup = false; - option.Header.DisplayType = ReportDisplayType.Export; - break; case HeaderMetadata.ImagePrimary: option.Column = (i, r) => this.GetBoolString(r.HasImageTagsPrimary); option.Header.ItemViewType = ItemViewType.TagsPrimaryImage; @@ -633,7 +615,6 @@ namespace MediaBrowser.Api.Reports { Id = item.Id.ToString("N"), HasLockData = item.IsLocked, - IsUnidentified = item.IsUnidentified, HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false, HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0), HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0), diff --git a/MediaBrowser.Api/Reports/Model/ReportRow.cs b/MediaBrowser.Api/Reports/Model/ReportRow.cs index 3f66b8479b..1a46b72b7a 100644 --- a/MediaBrowser.Api/Reports/Model/ReportRow.cs +++ b/MediaBrowser.Api/Reports/Model/ReportRow.cs @@ -56,10 +56,6 @@ namespace MediaBrowser.Api.Reports /// <value> true if this object has specials, false if not. </value> public bool HasSpecials { get; set; } - /// <summary> Gets or sets a value indicating whether this object is unidentified. </summary> - /// <value> true if this object is unidentified, false if not. </value> - public bool IsUnidentified { get; set; } - /// <summary> Gets or sets the columns. </summary> /// <value> The columns. </value> public List<ReportItem> Columns { get; set; } diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index 82e7264f15..6c2886f5be 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -226,7 +226,6 @@ namespace MediaBrowser.Api.Reports NameStartsWithOrGreater = request.NameStartsWithOrGreater, HasImdbId = request.HasImdbId, IsYearMismatched = request.IsYearMismatched, - IsUnidentified = request.IsUnidentified, IsPlaceHolder = request.IsPlaceHolder, IsLocked = request.IsLocked, IsInBoxSet = request.IsInBoxSet, diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs index c9ee6337ff..fb694d6e13 100644 --- a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs +++ b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs @@ -213,7 +213,7 @@ namespace MediaBrowser.Api.Reports }; foreach (var item in t) { - var ps = items.Where(x => x.People != null && x.SupportsPeople).SelectMany(x => x.People) + var ps = items.SelectMany(x => _libraryManager.GetPeople(x)) .Where(n => n.Type == item.ToString()) .GroupBy(x => x.Name) .OrderByDescending(x => x.Count()) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index e9ac45fa25..962334cdc3 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -69,10 +69,10 @@ namespace MediaBrowser.Api _config.Configuration.MergeMetadataAndImagesByName = true; _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; - _config.Configuration.EnableUserSpecificUserViews = true; _config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.DisableXmlSavers = true; _config.Configuration.DisableStartupScan = true; + _config.Configuration.EnableUserViews = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index c9280b6f63..0bfe7354d6 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -16,6 +16,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MimeTypes = MediaBrowser.Model.Net.MimeTypes; +using MediaBrowser.Common.IO; namespace MediaBrowser.Api.Subtitles { @@ -127,14 +128,16 @@ namespace MediaBrowser.Api.Subtitles private readonly ISubtitleEncoder _subtitleEncoder; private readonly IMediaSourceManager _mediaSourceManager; private readonly IProviderManager _providerManager; + private readonly IFileSystem _fileSystem; - public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager) + public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem) { _libraryManager = libraryManager; _subtitleManager = subtitleManager; _subtitleEncoder = subtitleEncoder; _mediaSourceManager = mediaSourceManager; _providerManager = providerManager; + _fileSystem = fileSystem; } public async Task<object> Get(GetSubtitlePlaylist request) @@ -259,7 +262,7 @@ namespace MediaBrowser.Api.Subtitles await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) .ConfigureAwait(false); - _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions()); + _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem)); } catch (Exception ex) { diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index aa12269019..00935dd1e1 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -122,8 +122,7 @@ namespace MediaBrowser.Api.System try { - files = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) + files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) .Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase)) .ToList(); } @@ -149,8 +148,7 @@ namespace MediaBrowser.Api.System public object Get(GetLogFile request) { - var file = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) + var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) .First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase)); return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index 7db8e4dcad..4d844e6cbe 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -299,9 +299,6 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public bool? IsLocked { get; set; } - [ApiMember(Name = "IsUnidentified", Description = "Optional filter by items that are unidentified by internet metadata providers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public bool? IsUnidentified { get; set; } - [ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public bool? IsPlaceHolder { get; set; } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 7d3290c2f9..f1168ab7f4 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -192,7 +192,6 @@ namespace MediaBrowser.Api.UserLibrary NameStartsWithOrGreater = request.NameStartsWithOrGreater, HasImdbId = request.HasImdbId, IsYearMismatched = request.IsYearMismatched, - IsUnidentified = request.IsUnidentified, IsPlaceHolder = request.IsPlaceHolder, IsLocked = request.IsLocked, IsInBoxSet = request.IsInBoxSet, diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index a49ab85562..9d7c38d6f0 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -39,6 +39,17 @@ namespace MediaBrowser.Api.UserLibrary public string UserId { get; set; } } + [Route("/Users/{UserId}/GroupingOptions", "GET")] + public class GetGroupingOptions : IReturn<List<SpecialViewOption>> + { + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UserId { get; set; } + } + public class UserViewsService : BaseApiService { private readonly IUserManager _userManager; @@ -105,6 +116,29 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(list); } + public async Task<object> Get(GetGroupingOptions request) + { + var user = _userManager.GetUserById(request.UserId); + + var views = user.RootFolder + .GetChildren(user, true) + .OfType<Folder>() + .Where(i => !UserView.IsExcludedFromGrouping(i)) + .ToList(); + + var list = views + .Select(i => new SpecialViewOption + { + Name = i.Name, + Id = i.Id.ToString("N") + + }) + .OrderBy(i => i.Name) + .ToList(); + + return ToOptimizedResult(list); + } + private bool IsEligibleForSpecialView(ICollectionFolder view) { var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos }; diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config index 6df1662040..0cdb26bd59 100644 --- a/MediaBrowser.Api/packages.config +++ b/MediaBrowser.Api/packages.config @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="morelinq" version="1.1.0" targetFramework="net45" /> + <package id="morelinq" version="1.1.1" targetFramework="net45" /> </packages>
\ No newline at end of file |
