diff options
177 files changed, 1615 insertions, 2247 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4abd39cfc..137a689e8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -8,23 +8,23 @@ assignees: '' --- **Describe the bug** -A clear and concise description of what the bug is. +<!-- A clear and concise description of what the bug is. --> **To Reproduce** -Steps to reproduce the behavior: +<!-- Steps to reproduce the behavior: --> 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** -A clear and concise description of what you expected to happen. +<!-- A clear and concise description of what you expected to happen. --> **Logs** -Please paste any log errors. +<!-- Please paste any log errors. --> **Screenshots** -If applicable, add screenshots to help explain your problem. +<!-- If applicable, add screenshots to help explain your problem. --> **System (please complete the following information):** - OS: [e.g. Docker, Debian, Windows] @@ -32,4 +32,4 @@ If applicable, add screenshots to help explain your problem. - Jellyfin Version: [e.g. 10.0.1] **Additional context** -Add any other context about the problem here. +<!-- Add any other context about the problem here. --> diff --git a/.github/ISSUE_TEMPLATE/enhancement-request.md b/.github/ISSUE_TEMPLATE/enhancement-request.md index 57c0d4cae..a655b60f5 100644 --- a/.github/ISSUE_TEMPLATE/enhancement-request.md +++ b/.github/ISSUE_TEMPLATE/enhancement-request.md @@ -8,13 +8,13 @@ assignees: '' --- **Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --> **Describe the solution you'd like** -A clear and concise description of what you want to happen. +<!-- A clear and concise description of what you want to happen. --> **Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +<!-- A clear and concise description of any alternative solutions or features you've considered. --> **Additional context** -Add any other context or screenshots about the feature request here. +<!-- Add any other context or screenshots about the feature request here. --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index a2ce07245..3cbc8cbb9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -8,7 +8,7 @@ assignees: '' --- **Describe the feature you'd like** -A clear and concise description of what you want to happen. +<!-- A clear and concise description of what you want to happen. --> **Additional context** -Add any other context or screenshots about the feature request here. +<!-- Add any other context or screenshots about the feature request here. --> diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b2b3cf241..967be0fb7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,9 +1,11 @@ +<!-- Ensure your title is short, descriptive, and in the imperative mood (Fix X, Change Y, instead of Fixed X, Changed Y). For a good inspiration of what to write in commit messages and PRs please review https://chris.beams.io/posts/git-commit/ and our https://jellyfin.readthedocs.io/en/latest/developer-docs/contributing/ page. +--> **Changes** -Describe your changes here in 1-5 sentences. +<!-- Describe your changes here in 1-5 sentences. --> **Issues** -Tag any issues that this PR solves here. -Fixes # +<!-- Tag any issues that this PR solves here. +ex. Fixes # --> diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs index 4cd636023..4360ff1d4 100644 --- a/BDInfo/BDROM.cs +++ b/BDInfo/BDROM.cs @@ -92,7 +92,7 @@ namespace BDInfo } DirectoryRoot = - _fileSystem.GetDirectoryInfo(_fileSystem.GetDirectoryName(DirectoryBDMV.FullName)); + _fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName)); DirectoryBDJO = GetDirectory("BDJO", DirectoryBDMV, 0); DirectoryCLIPINF = @@ -150,7 +150,7 @@ namespace BDInfo Is3D = true; } - if (_fileSystem.FileExists(Path.Combine(DirectoryRoot.FullName, "FilmIndex.xml"))) + if (File.Exists(Path.Combine(DirectoryRoot.FullName, "FilmIndex.xml"))) { IsDBOX = true; } @@ -345,7 +345,7 @@ namespace BDInfo { return dir; } - var parentFolder = _fileSystem.GetDirectoryName(dir.FullName); + var parentFolder = Path.GetDirectoryName(dir.FullName); if (string.IsNullOrEmpty(parentFolder)) { dir = null; diff --git a/BDInfo/TSPlaylistFile.cs b/BDInfo/TSPlaylistFile.cs index 8c98d44d7..6e91f6e40 100644 --- a/BDInfo/TSPlaylistFile.cs +++ b/BDInfo/TSPlaylistFile.cs @@ -1,4 +1,4 @@ -//============================================================================ +//============================================================================ // BDInfo - Blu-ray Video and Audio Analysis Tool // Copyright © 2010 Cinema Squid // @@ -231,7 +231,7 @@ namespace BDInfo Streams.Clear(); StreamClips.Clear(); - fileStream = _fileSystem.OpenRead(FileInfo.FullName); + fileStream = File.OpenRead(FileInfo.FullName); fileReader = new BinaryReader(fileStream); byte[] data = new byte[fileStream.Length]; diff --git a/BDInfo/TSStreamClipFile.cs b/BDInfo/TSStreamClipFile.cs index 3396f4c71..d840542ba 100644 --- a/BDInfo/TSStreamClipFile.cs +++ b/BDInfo/TSStreamClipFile.cs @@ -1,4 +1,4 @@ -//============================================================================ +//============================================================================ // BDInfo - Blu-ray Video and Audio Analysis Tool // Copyright © 2010 Cinema Squid // @@ -57,7 +57,7 @@ namespace BDInfo #endif Streams.Clear(); - fileStream = _fileSystem.OpenRead(FileInfo.FullName); + fileStream = File.OpenRead(FileInfo.FullName); fileReader = new BinaryReader(fileStream); byte[] data = new byte[fileStream.Length]; diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d918b7b95..eca16ad38 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -16,6 +16,7 @@ - [wtayl0r](https://github.com/wtayl0r) - [TtheCreator](https://github.com/Tthecreator) - [LogicalPhallacy](https://github.com/LogicalPhallacy/) + - [RazeLighter777](https://github.com/RazeLighter777) # Emby Contributors diff --git a/Dockerfile b/Dockerfile index b014afcd2..c79d6f8ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,5 @@ ARG DOTNET_VERSION=2 - -# Download ffmpeg first to allow quicker rebuild of other layers -FROM alpine as ffmpeg -ARG FFMPEG_URL=https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.0.3-64bit-static.tar.xz -RUN wget ${FFMPEG_URL} -O - | tar Jxf - \ - && mkdir ffmpeg-bin \ - && mv ffmpeg*/ffmpeg ffmpeg-bin \ - && mv ffmpeg*/ffprobe ffmpeg-bin - - FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder WORKDIR /repo COPY . . @@ -20,13 +10,8 @@ RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ --output /jellyfin \ Jellyfin.Server - +FROM jrottenberg/ffmpeg:4.0-scratch as ffmpeg FROM microsoft/dotnet:${DOTNET_VERSION}-runtime -COPY --from=builder /jellyfin /jellyfin -COPY --from=ffmpeg /ffmpeg-bin/* /usr/bin/ -EXPOSE 8096 -VOLUME /config /media - # libfontconfig1 is required for Skia RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ @@ -34,4 +19,8 @@ RUN apt-get update \ && apt-get clean autoclean \ && apt-get autoremove \ && rm -rf /var/lib/{apt,dpkg,cache,log} +COPY --from=ffmpeg / / +COPY --from=builder /jellyfin /jellyfin +EXPOSE 8096 +VOLUME /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config diff --git a/Dockerfile.arm b/Dockerfile.arm index 239fdd1c1..657cb4ac6 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -16,9 +16,9 @@ RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7 -COPY --from=builder /jellyfin /jellyfin -EXPOSE 8096 RUN apt-get update \ && apt-get install -y ffmpeg +COPY --from=builder /jellyfin /jellyfin +EXPOSE 8096 VOLUME /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 6d7aa2118..979dfc1dc 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -24,10 +24,10 @@ RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8 +RUN apt-get update \ + && apt-get install -y ffmpeg COPY --from=qemu_extract qemu-* /usr/bin COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 -RUN apt-get update \ - && apt-get install -y ffmpeg VOLUME /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config diff --git a/Emby.Dlna/ContentDirectory/ContentDirectory.cs b/Emby.Dlna/ContentDirectory/ContentDirectory.cs index cd21599d0..b0fec90e6 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectory.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectory.cs @@ -76,7 +76,6 @@ namespace Emby.Dlna.ContentDirectory _dlna.GetDefaultProfile(); var serverAddress = request.RequestedUrl.Substring(0, request.RequestedUrl.IndexOf("/dlna", StringComparison.OrdinalIgnoreCase)); - string accessToken = null; var user = GetUser(profile); @@ -85,7 +84,7 @@ namespace Emby.Dlna.ContentDirectory _libraryManager, profile, serverAddress, - accessToken, + null, _imageProcessor, _userDataManager, user, diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 2f6a0ecee..2d8bb87f9 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -483,27 +483,26 @@ namespace Emby.Dlna.ContentDirectory return GetGenreItems(item, Guid.Empty, user, sort, startIndex, limit); } - if (!stubType.HasValue || stubType.Value != StubType.Folder) + if ((!stubType.HasValue || stubType.Value != StubType.Folder) + && item is IHasCollectionType collectionFolder) { - var collectionFolder = item as IHasCollectionType; - if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetMusicFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetMovieFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetTvFolders(item, user, stubType, sort, startIndex, limit); } - - if (collectionFolder != null && string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetLiveTvChannels(item, user, stubType, sort, startIndex, limit); } diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 34ad3f8fb..e4a9cbfc6 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -1088,8 +1088,8 @@ namespace Emby.Dlna.Didl //{ // var size = _imageProcessor.GetImageSize(imageInfo); - // width = Convert.ToInt32(size.Width); - // height = Convert.ToInt32(size.Height); + // width = size.Width; + // height = size.Height; //} //catch //{ @@ -1162,8 +1162,7 @@ namespace Emby.Dlna.Didl info.ImageTag, format, maxWidth.ToString(CultureInfo.InvariantCulture), - maxHeight.ToString(CultureInfo.InvariantCulture) - ); + maxHeight.ToString(CultureInfo.InvariantCulture)); var width = info.Width; var height = info.Height; @@ -1172,15 +1171,11 @@ namespace Emby.Dlna.Didl if (width.HasValue && height.HasValue) { - var newSize = DrawingUtils.Resize(new ImageSize - { - Height = height.Value, - Width = width.Value - - }, 0, 0, maxWidth, maxHeight); + var newSize = DrawingUtils.Resize( + new ImageDimensions(width.Value, height.Value), 0, 0, maxWidth, maxHeight); - width = Convert.ToInt32(newSize.Width); - height = Convert.ToInt32(newSize.Height); + width = newSize.Width; + height = newSize.Height; var normalizedFormat = format .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase); diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index f795b58cb..fd7b408fd 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -379,7 +379,7 @@ namespace Emby.Dlna if (!fileInfo.Exists || fileInfo.Length != stream.Length) { - _fileSystem.CreateDirectory(systemProfilesPath); + Directory.CreateDirectory(systemProfilesPath); using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { @@ -390,7 +390,7 @@ namespace Emby.Dlna } // Not necessary, but just to make it easy to find - _fileSystem.CreateDirectory(UserProfilesPath); + Directory.CreateDirectory(UserProfilesPath); } public void DeleteProfile(string id) diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 8e82e6f69..790625705 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -162,9 +162,7 @@ namespace Emby.Dlna.PlayTo uuid = location.GetMD5().ToString("N"); } - string deviceName = null; - - var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersion, uuid, deviceName, uri.OriginalString, null); + var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersion, uuid, null, uri.OriginalString, null); var controller = sessionInfo.SessionControllers.OfType<PlayToController>().FirstOrDefault(); @@ -172,7 +170,7 @@ namespace Emby.Dlna.PlayTo { var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false); - deviceName = device.Properties.Name; + string deviceName = device.Properties.Name; _sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName); @@ -186,8 +184,6 @@ namespace Emby.Dlna.PlayTo serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress); } - string accessToken = null; - controller = new PlayToController(sessionInfo, _sessionManager, _libraryManager, @@ -196,7 +192,7 @@ namespace Emby.Dlna.PlayTo _userManager, _imageProcessor, serverAddress, - accessToken, + null, _deviceDiscovery, _userDataManager, _localization, diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index c36d42194..9f97baf77 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -6,12 +6,6 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="SkiaSharp" Version="1.68.0" /> - <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.0" /> - <PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.0" /> - </ItemGroup> - - <ItemGroup> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index c750b60e2..4901561eb 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -18,7 +18,6 @@ using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; -using SkiaSharp; namespace Emby.Drawing { @@ -66,7 +65,7 @@ namespace Emby.Drawing _appPaths = appPaths; ImageEnhancers = Array.Empty<IImageEnhancer>(); - + ImageHelper.ImageProcessor = this; } @@ -168,10 +167,10 @@ namespace Emby.Drawing string originalImagePath = originalImage.Path; DateTime dateModified = originalImage.DateModified; - ImageSize? originalImageSize = null; + ImageDimensions? originalImageSize = null; if (originalImage.Width > 0 && originalImage.Height > 0) { - originalImageSize = new ImageSize(originalImage.Width, originalImage.Height); + originalImageSize = new ImageDimensions(originalImage.Width, originalImage.Height); } if (!_imageEncoder.SupportsImageEncoding) @@ -231,7 +230,7 @@ namespace Emby.Drawing return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); } - ImageSize newSize = ImageHelper.GetNewImageSize(options, null); + ImageDimensions newSize = ImageHelper.GetNewImageSize(options, null); int quality = options.Quality; ImageFormat outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); @@ -245,7 +244,7 @@ namespace Emby.Drawing try { - if (!_fileSystem.FileExists(cacheFilePath)) + if (!File.Exists(cacheFilePath)) { if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath)) { @@ -334,7 +333,7 @@ namespace Emby.Drawing /// <summary> /// Gets the cache file path based on a set of parameters /// </summary> - private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer) + private string GetCacheFilePath(string originalPath, ImageDimensions outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer) { var filename = originalPath + "width=" + outputSize.Width @@ -378,26 +377,25 @@ namespace Emby.Drawing return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLower()); } - public ImageSize GetImageSize(BaseItem item, ItemImageInfo info) + public ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info) => GetImageSize(item, info, true); - public ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem) + public ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem) { int width = info.Width; int height = info.Height; if (height > 0 && width > 0) { - return new ImageSize(width, height); + return new ImageDimensions(width, height); } string path = info.Path; _logger.LogInformation("Getting image size for item {ItemType} {Path}", item.GetType().Name, path); - var size = GetImageSize(path); - - info.Height = Convert.ToInt32(size.Height); - info.Width = Convert.ToInt32(size.Width); + ImageDimensions size = GetImageSize(path); + info.Width = size.Width; + info.Height = size.Height; if (updateItem) { @@ -410,20 +408,8 @@ namespace Emby.Drawing /// <summary> /// Gets the size of the image. /// </summary> - public ImageSize GetImageSize(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - using (var s = new SKFileStream(path)) - using (var codec = SKCodec.Create(s)) - { - var info = codec.Info; - return new ImageSize(info.Width, info.Height); - } - } + public ImageDimensions GetImageSize(string path) + => _imageEncoder.GetImageSize(path); /// <summary> /// Gets the image cache tag. @@ -640,12 +626,12 @@ namespace Emby.Drawing try { // Check again in case of contention - if (_fileSystem.FileExists(enhancedImagePath)) + if (File.Exists(enhancedImagePath)) { return (enhancedImagePath, treatmentRequiresTransparency); } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath)); + Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false); diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index e6f205a1f..14f0424ac 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -37,7 +37,7 @@ namespace Emby.Drawing public bool SupportsImageEncoding => false; - public ImageSize GetImageSize(string path) + public ImageDimensions GetImageSize(string path) { throw new NotImplementedException(); } diff --git a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs index ac486f167..c5564fd61 100644 --- a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs +++ b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs @@ -39,7 +39,7 @@ namespace IsoMounter _logger = logger; ProcessFactory = processFactory; - MountPointRoot = FileSystem.DirectorySeparatorChar + "tmp" + FileSystem.DirectorySeparatorChar + "Emby"; + MountPointRoot = Path.DirectorySeparatorChar + "tmp" + Path.DirectorySeparatorChar + "Emby"; _logger.LogDebug( "[{0}] System PATH is currently set to [{1}].", @@ -214,9 +214,9 @@ namespace IsoMounter { string path = test.Trim(); - if (!string.IsNullOrEmpty(path) && FileSystem.FileExists(path = Path.Combine(path, name))) + if (!string.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, name))) { - return FileSystem.GetFullPath(path); + return Path.GetFullPath(path); } } @@ -327,7 +327,7 @@ namespace IsoMounter try { - FileSystem.CreateDirectory(mountPoint); + Directory.CreateDirectory(mountPoint); } catch (UnauthorizedAccessException) { @@ -377,7 +377,7 @@ namespace IsoMounter try { - FileSystem.DeleteDirectory(mountPoint, false); + Directory.Delete(mountPoint, false); } catch (Exception ex) { @@ -455,7 +455,7 @@ namespace IsoMounter try { - FileSystem.DeleteDirectory(mount.MountedPath, false); + Directory.Delete(mount.MountedPath, false); } catch (Exception ex) { diff --git a/Emby.Naming/AudioBook/AudioBookResolver.cs b/Emby.Naming/AudioBook/AudioBookResolver.cs index 67451a639..67ab62e80 100644 --- a/Emby.Naming/AudioBook/AudioBookResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookResolver.cs @@ -36,7 +36,7 @@ namespace Emby.Naming.AudioBook return null; } - var extension = Path.GetExtension(path) ?? string.Empty; + var extension = Path.GetExtension(path); // Check supported extensions if (!_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs index 0506d0734..ef97b8739 100644 --- a/Emby.Naming/Video/VideoListResolver.cs +++ b/Emby.Naming/Video/VideoListResolver.cs @@ -175,71 +175,23 @@ namespace Emby.Naming.Video return videos; } - var list = new List<VideoInfo>(); - var folderName = Path.GetFileName(Path.GetDirectoryName(videos[0].Files[0].Path)); if (!string.IsNullOrEmpty(folderName) && folderName.Length > 1) { - if (videos.All(i => i.Files.Count == 1 && IsEligibleForMultiVersion(folderName, i.Files[0].Path))) - { - // Enforce the multi-version limit - if (videos.Count <= 8 && HaveSameYear(videos)) - { - var ordered = videos.OrderBy(i => i.Name).ToList(); - - list.Add(ordered[0]); - - list[0].AlternateVersions = ordered.Skip(1).Select(i => i.Files[0]).ToList(); - list[0].Name = folderName; - list[0].Extras.AddRange(ordered.Skip(1).SelectMany(i => i.Extras)); + var ordered = videos.OrderBy(i => i.Name); - return list; - } - } + return ordered.GroupBy(v => new {v.Name, v.Year}).Select(group => new VideoInfo + { + Name = folderName, + Year = group.First().Year, + Files = group.First().Files, + AlternateVersions = group.Skip(1).Select(i => i.Files[0]).ToList(), + Extras = group.First().Extras.Concat(group.Skip(1).SelectMany(i => i.Extras)).ToList() + }); } return videos; - //foreach (var video in videos.OrderBy(i => i.Name)) - //{ - // var match = list - // .FirstOrDefault(i => string.Equals(i.Name, video.Name, StringComparison.OrdinalIgnoreCase)); - - // if (match != null && video.Files.Count == 1 && match.Files.Count == 1) - // { - // match.AlternateVersions.Add(video.Files[0]); - // match.Extras.AddRange(video.Extras); - // } - // else - // { - // list.Add(video); - // } - //} - - //return list; - } - - private bool HaveSameYear(List<VideoInfo> videos) - { - return videos.Select(i => i.Year ?? -1).Distinct().Count() < 2; - } - - private bool IsEligibleForMultiVersion(string folderName, string testFilename) - { - testFilename = Path.GetFileNameWithoutExtension(testFilename); - - if (string.Equals(folderName, testFilename, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (testFilename.StartsWith(folderName, StringComparison.OrdinalIgnoreCase)) - { - testFilename = testFilename.Substring(folderName.Length).Trim(); - return testFilename.StartsWith("-", StringComparison.OrdinalIgnoreCase) || Regex.Replace(testFilename, @"\[([^]]*)\]", "").Trim() == string.Empty; - } - - return false; } private List<VideoFileInfo> GetExtras(IEnumerable<VideoFileInfo> remainingFiles, List<string> baseNames) diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 4e483ad5b..aaebe1a21 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -185,8 +185,8 @@ namespace Emby.Photos if (size.Width > 0 && size.Height > 0) { - item.Width = Convert.ToInt32(size.Width); - item.Height = Convert.ToInt32(size.Height); + item.Width = size.Width; + item.Height = size.Height; } } catch (ArgumentException) diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index aef72c697..efe8f98ec 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -93,18 +92,18 @@ namespace Emby.Server.Implementations.Activity _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; } - async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) + void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("CameraImageUploadedFrom"), e.Argument.Device.Name), Type = NotificationType.CameraImageUploaded.ToString() }); } - async void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) + void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserLockedOutWithName"), e.Argument.Name), Type = NotificationType.UserLockedOut.ToString(), @@ -112,9 +111,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) + void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"), e.Provider, Notifications.Notifications.GetItemName(e.Item)), Type = "SubtitleDownloadFailure", @@ -123,7 +122,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) + void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) { var item = e.MediaInfo; @@ -146,7 +145,7 @@ namespace Emby.Server.Implementations.Activity var user = e.Users.First(); - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, GetItemName(item), e.DeviceName), Type = GetPlaybackStoppedNotificationType(item.MediaType), @@ -154,7 +153,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) + void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) { var item = e.MediaInfo; @@ -177,7 +176,7 @@ namespace Emby.Server.Implementations.Activity var user = e.Users.First(); - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, GetItemName(item), e.DeviceName), Type = GetPlaybackNotificationType(item.MediaType), @@ -238,7 +237,7 @@ namespace Emby.Server.Implementations.Activity return null; } - async void _sessionManager_SessionEnded(object sender, SessionEventArgs e) + void _sessionManager_SessionEnded(object sender, SessionEventArgs e) { string name; var session = e.SessionInfo; @@ -255,7 +254,7 @@ namespace Emby.Server.Implementations.Activity name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = name, Type = "SessionEnded", @@ -264,11 +263,11 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e) + void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e) { var user = e.Argument.User; - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), user.Name), Type = "AuthenticationSucceeded", @@ -277,9 +276,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e) + void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username), Type = "AuthenticationFailed", @@ -288,9 +287,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) + void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("MessageApplicationUpdatedTo"), e.Argument.versionStr), Type = NotificationType.ApplicationUpdateInstalled.ToString(), @@ -298,27 +297,27 @@ namespace Emby.Server.Implementations.Activity }); } - async void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key), Type = "NamedConfigurationUpdated" }); } - async void _config_ConfigurationUpdated(object sender, EventArgs e) + void _config_ConfigurationUpdated(object sender, EventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"), Type = "ServerConfigurationUpdated" }); } - async void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e) + void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserPolicyUpdatedWithName"), e.Argument.Name), Type = "UserPolicyUpdated", @@ -326,18 +325,18 @@ namespace Emby.Server.Implementations.Activity }); } - async void _userManager_UserDeleted(object sender, GenericEventArgs<User> e) + void _userManager_UserDeleted(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name), Type = "UserDeleted" }); } - async void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e) + void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name), Type = "UserPasswordChanged", @@ -345,9 +344,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _userManager_UserCreated(object sender, GenericEventArgs<User> e) + void _userManager_UserCreated(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name), Type = "UserCreated", @@ -355,9 +354,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e) + void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)), Type = "SubtitlesDownloaded", @@ -366,7 +365,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + void _sessionManager_SessionStarted(object sender, SessionEventArgs e) { string name; var session = e.SessionInfo; @@ -383,7 +382,7 @@ namespace Emby.Server.Implementations.Activity name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = name, Type = "SessionStarted", @@ -392,9 +391,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) + void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name), Type = NotificationType.PluginUpdateInstalled.ToString(), @@ -403,18 +402,18 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) + void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name), Type = NotificationType.PluginUninstalled.ToString() }); } - async void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) + void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name), Type = NotificationType.PluginInstalled.ToString(), @@ -422,11 +421,11 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) + void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) { var installationInfo = e.InstallationInfo; - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("NameInstallFailed"), installationInfo.Name), Type = NotificationType.InstallationFailed.ToString(), @@ -435,7 +434,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) + void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) { var result = e.Result; var task = e.Task; @@ -462,7 +461,7 @@ namespace Emby.Server.Implementations.Activity vals.Add(e.Result.LongErrorMessage); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), Type = NotificationType.TaskFailed.ToString(), @@ -473,11 +472,11 @@ namespace Emby.Server.Implementations.Activity } } - private async Task CreateLogEntry(ActivityLogEntry entry) + private void CreateLogEntry(ActivityLogEntry entry) { try { - await _activityManager.CreateAsync(entry); + _activityManager.Create(entry); } catch { @@ -502,7 +501,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped; - _subManager.SubtitlesDownloaded -= _subManager_SubtitlesDownloaded; _subManager.SubtitleDownloadFailure -= _subManager_SubtitleDownloadFailure; _userManager.UserCreated -= _userManager_UserCreated; diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs index 8fcacb002..6febcc2f7 100644 --- a/Emby.Server.Implementations/Activity/ActivityManager.cs +++ b/Emby.Server.Implementations/Activity/ActivityManager.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; +using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Activity @@ -27,38 +26,20 @@ namespace Emby.Server.Implementations.Activity _userManager = userManager; } - public async Task CreateAsync(ActivityLogEntry entry) + public void Create(ActivityLogEntry entry) { entry.Date = DateTime.UtcNow; - await _repo.CreateAsync(entry); + _repo.Create(entry); EntryCreated?.Invoke(this, new GenericEventArgs<ActivityLogEntry>(entry)); } - public IEnumerable<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) { - var result = _repo.GetActivityLogEntries(); + var result = _repo.GetActivityLogEntries(minDate, hasUserId, startIndex, limit); - if (minDate.HasValue) - { - result = result.Where(x => x.Date >= minDate.Value); - } - if (hasUserId.HasValue) - { - result = result.Where(x => x.UserId != null && x.UserId != Guid.Empty); - } - if (startIndex.HasValue) - { - result = result.Where(x => x.Id >= startIndex.Value); - } - if (limit.HasValue) - { - result = result.Take(limit.Value); - } - - // Add images for each user - foreach (var item in result) + foreach (var item in result.Items.Where(i => !i.UserId.Equals(Guid.Empty))) { var user = _userManager.GetUserById(item.UserId); @@ -69,7 +50,12 @@ namespace Emby.Server.Implementations.Activity } } - return result.AsEnumerable(); + return result; + } + + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit) + { + return GetActivityLogEntries(minDate, null, startIndex, limit); } } } diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index af0b20d92..aeed8b6f1 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -1,37 +1,310 @@ +using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; -using System.Threading.Tasks; +using Emby.Server.Implementations.Data; +using MediaBrowser.Controller; using MediaBrowser.Model.Activity; -using Microsoft.EntityFrameworkCore; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; +using Microsoft.Extensions.Logging; +using SQLitePCL.pretty; namespace Emby.Server.Implementations.Activity { - public class ActivityRepository : DbContext, IActivityRepository + public class ActivityRepository : BaseSqliteRepository, IActivityRepository { - protected string _dataDirPath; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + protected IFileSystem FileSystem { get; private set; } - public DbSet<ActivityLogEntry> ActivityLogs { get; set; } + public ActivityRepository(ILoggerFactory loggerFactory, IServerApplicationPaths appPaths, IFileSystem fileSystem) + : base(loggerFactory.CreateLogger(nameof(ActivityRepository))) + { + DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db"); + FileSystem = fileSystem; + } - public ActivityRepository(string dataDirPath) + public void Initialize() { - _dataDirPath = dataDirPath; + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error loading database file. Will reset and retry."); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + private void InitializeInternal() { - // Ensure the dir exists - Directory.CreateDirectory(_dataDirPath); + using (var connection = CreateConnection()) + { + RunDefaultInitialization(connection); + + connection.RunQueries(new[] + { + "create table if not exists ActivityLog (Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Overview TEXT, ShortOverview TEXT, Type TEXT NOT NULL, ItemId TEXT, UserId TEXT, DateCreated DATETIME NOT NULL, LogSeverity TEXT NOT NULL)", + "drop index if exists idx_ActivityLogEntries" + }); + + TryMigrate(connection); + } + } - optionsBuilder.UseSqlite($"Filename={Path.Combine(_dataDirPath, "activitylog.sqlite.db")}"); + private void TryMigrate(ManagedConnection connection) + { + try + { + if (TableExists(connection, "ActivityLogEntries")) + { + connection.RunQueries(new[] + { + "INSERT INTO ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) SELECT Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity FROM ActivityLogEntries", + "drop table if exists ActivityLogEntries" + }); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error migrating activity log database"); + } } - public async Task CreateAsync(ActivityLogEntry entry) + private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLog"; + + public void Create(ActivityLogEntry entry) { - await ActivityLogs.AddAsync(entry); - await SaveChangesAsync(); + if (entry == null) + { + throw new ArgumentNullException(nameof(entry)); + } + + using (WriteLock.Write()) + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("insert into ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)")) + { + statement.TryBind("@Name", entry.Name); + + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) + { + statement.TryBindNull("@UserId"); + } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); + } + } + + public void Update(ActivityLogEntry entry) + { + if (entry == null) + { + throw new ArgumentNullException(nameof(entry)); + } + + using (WriteLock.Write()) + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("Update ActivityLog set Name=@Name,Overview=@Overview,ShortOverview=@ShortOverview,Type=@Type,ItemId=@ItemId,UserId=@UserId,DateCreated=@DateCreated,LogSeverity=@LogSeverity where Id=@Id")) + { + statement.TryBind("@Id", entry.Id); + + statement.TryBind("@Name", entry.Name); + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) + { + statement.TryBindNull("@UserId"); + } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); + } + } + + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) + { + using (WriteLock.Read()) + using (var connection = CreateConnection(true)) + { + var commandText = BaseActivitySelectText; + var whereClauses = new List<string>(); + + if (minDate.HasValue) + { + whereClauses.Add("DateCreated>=@DateCreated"); + } + if (hasUserId.HasValue) + { + if (hasUserId.Value) + { + whereClauses.Add("UserId not null"); + } + else + { + whereClauses.Add("UserId is null"); + } + } + + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + if (startIndex.HasValue && startIndex.Value > 0) + { + var pagingWhereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLog {0} ORDER BY DateCreated DESC LIMIT {1})", + pagingWhereText, + startIndex.Value.ToString(_usCulture))); + } + + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + commandText += whereText; + + commandText += " ORDER BY DateCreated DESC"; + + if (limit.HasValue) + { + commandText += " LIMIT " + limit.Value.ToString(_usCulture); + } + + var statementTexts = new List<string>(); + statementTexts.Add(commandText); + statementTexts.Add("select count (Id) from ActivityLog" + whereTextWithoutPaging); + + return connection.RunInTransaction(db => + { + var list = new List<ActivityLogEntry>(); + var result = new QueryResult<ActivityLogEntry>(); + + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + if (minDate.HasValue) + { + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); + } + + foreach (var row in statement.ExecuteQuery()) + { + list.Add(GetEntry(row)); + } + } + + using (var statement = statements[1]) + { + if (minDate.HasValue) + { + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); + } + + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } + + result.Items = list.ToArray(); + return result; + + }, ReadTransactionMode); + } } - public IQueryable<ActivityLogEntry> GetActivityLogEntries() - => ActivityLogs; + private static ActivityLogEntry GetEntry(IReadOnlyList<IResultSetValue> reader) + { + var index = 0; + + var info = new ActivityLogEntry + { + Id = reader[index].ToInt64() + }; + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Name = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Overview = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.ShortOverview = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Type = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.ItemId = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.UserId = new Guid(reader[index].ToString()); + } + + index++; + info.Date = reader[index].ReadDateTime(); + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Severity = (LogLevel)Enum.Parse(typeof(LogLevel), reader[index].ToString(), true); + } + + return info; + } } } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 59c7c655f..90b43bc59 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -127,7 +127,7 @@ namespace Emby.Server.Implementations.AppBase Logger.LogInformation("Saving system configuration"); var path = CommonApplicationPaths.SystemConfigurationFilePath; - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_configurationSyncLock) { @@ -197,7 +197,7 @@ namespace Emby.Server.Implementations.AppBase && !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath)) { // Validate - if (!FileSystem.DirectoryExists(newPath)) + if (!Directory.Exists(newPath)) { throw new FileNotFoundException(string.Format("{0} does not exist.", newPath)); } @@ -209,8 +209,7 @@ namespace Emby.Server.Implementations.AppBase protected void EnsureWriteAccess(string path) { var file = Path.Combine(path, Guid.NewGuid().ToString()); - - FileSystem.WriteAllText(file, string.Empty); + File.WriteAllText(file, string.Empty); FileSystem.DeleteFile(file); } @@ -246,13 +245,14 @@ namespace Emby.Server.Implementations.AppBase private object LoadConfiguration(string path, Type configurationType) { - try + if (!File.Exists(path)) { - return XmlSerializer.DeserializeFromFile(configurationType, path); + return Activator.CreateInstance(configurationType); } - catch (FileNotFoundException) + + try { - return Activator.CreateInstance(configurationType); + return XmlSerializer.DeserializeFromFile(configurationType, path); } catch (IOException) { @@ -293,7 +293,7 @@ namespace Emby.Server.Implementations.AppBase _configurations.AddOrUpdate(key, configuration, (k, v) => configuration); var path = GetConfigurationFile(key); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_configurationSyncLock) { diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index ee6da95fe..3faad76e7 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.AppBase // Use try/catch to avoid the extra file system lookup using File.Exists try { - buffer = fileSystem.ReadAllBytes(path); + buffer = File.ReadAllBytes(path); configuration = xmlSerializer.DeserializeFromBytes(type, buffer); } @@ -48,10 +48,10 @@ namespace Emby.Server.Implementations.AppBase // If the file didn't exist before, or if something has changed, re-save if (buffer == null || !buffer.SequenceEqual(newBytes)) { - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); // Save it after load in case we got new items - fileSystem.WriteAllBytes(path, newBytes); + File.WriteAllBytes(path, newBytes); } return configuration; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f5a4f1581..31dad48be 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -112,7 +112,6 @@ using ServiceStack; using ServiceStack.Text.Jsv; using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; -using UtfUnknown; namespace Emby.Server.Implementations { @@ -244,8 +243,6 @@ namespace Emby.Server.Implementations /// </summary> protected readonly SimpleInjector.Container Container = new SimpleInjector.Container(); - protected ISystemEvents SystemEvents { get; set; } - /// <summary> /// Gets the server configuration manager. /// </summary> @@ -317,7 +314,7 @@ namespace Emby.Server.Implementations private IUserDataManager UserDataManager { get; set; } private IUserRepository UserRepository { get; set; } internal IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; } - internal IItemRepository ItemRepository { get; set; } + internal SqliteItemRepository ItemRepository { get; set; } private INotificationManager NotificationManager { get; set; } private ISubtitleManager SubtitleManager { get; set; } @@ -371,7 +368,6 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, - ISystemEvents systemEvents, INetworkManager networkManager) { @@ -383,7 +379,6 @@ namespace Emby.Server.Implementations NetworkManager = networkManager; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; EnvironmentInfo = environmentInfo; - SystemEvents = systemEvents; ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; @@ -466,9 +461,8 @@ namespace Emby.Server.Implementations private static Tuple<Assembly, string> GetAssembly(Type type) { var assembly = type.GetTypeInfo().Assembly; - string path = null; - return new Tuple<Assembly, string>(assembly, path); + return new Tuple<Assembly, string>(assembly, null); } public virtual IStreamHelper CreateStreamHelper() @@ -709,7 +703,7 @@ namespace Emby.Server.Implementations } } - public async Task InitAsync() + public void Init() { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; @@ -739,7 +733,7 @@ namespace Emby.Server.Implementations SetHttpLimit(); - await RegisterResourcesAsync(); + RegisterResources(); FindParts(); } @@ -754,7 +748,7 @@ namespace Emby.Server.Implementations /// <summary> /// Registers resources that classes will depend on /// </summary> - protected async Task RegisterResourcesAsync() + protected void RegisterResources() { RegisterSingleInstance(ConfigurationManager); RegisterSingleInstance<IApplicationHost>(this); @@ -762,7 +756,6 @@ namespace Emby.Server.Implementations RegisterSingleInstance<IApplicationPaths>(ApplicationPaths); RegisterSingleInstance(JsonSerializer); - RegisterSingleInstance(SystemEvents); RegisterSingleInstance(LoggerFactory, false); RegisterSingleInstance(Logger); @@ -779,7 +772,7 @@ namespace Emby.Server.Implementations IsoManager = new IsoManager(); RegisterSingleInstance(IsoManager); - TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager, SystemEvents); + TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager); RegisterSingleInstance(TaskManager); RegisterSingleInstance(XmlSerializer); @@ -836,9 +829,8 @@ namespace Emby.Server.Implementations DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); - var itemRepo = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo, FileSystemManager, EnvironmentInfo, TimerFactory); - ItemRepository = itemRepo; - RegisterSingleInstance(ItemRepository); + ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo); + RegisterSingleInstance<IItemRepository>(ItemRepository); AuthenticationRepository = GetAuthenticationRepository(); RegisterSingleInstance(AuthenticationRepository); @@ -853,7 +845,7 @@ namespace Emby.Server.Implementations var musicManager = new MusicManager(LibraryManager); RegisterSingleInstance<IMusicManager>(new MusicManager(LibraryManager)); - LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, SystemEvents, EnvironmentInfo); + LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, EnvironmentInfo); RegisterSingleInstance(LibraryMonitor); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LoggerFactory, LibraryManager, UserManager)); @@ -888,7 +880,7 @@ namespace Emby.Server.Implementations MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, TimerFactory, () => MediaEncoder); RegisterSingleInstance(MediaSourceManager); - SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, ServerConfigurationManager, LocalizationManager); + SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager); RegisterSingleInstance(SubtitleManager); ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); @@ -931,7 +923,7 @@ namespace Emby.Server.Implementations EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); RegisterSingleInstance(EncodingManager); - var activityLogRepo = await GetActivityLogRepositoryAsync(); + var activityLogRepo = GetActivityLogRepository(); RegisterSingleInstance(activityLogRepo); RegisterSingleInstance<IActivityManager>(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); @@ -956,7 +948,7 @@ namespace Emby.Server.Implementations ((UserManager)UserManager).Initialize(); ((UserDataManager)UserDataManager).Repository = userDataRepo; - itemRepo.Initialize(userDataRepo, UserManager); + ItemRepository.Initialize(userDataRepo, UserManager); ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; } @@ -1015,7 +1007,7 @@ namespace Emby.Server.Implementations try { - if (!FileSystemManager.FileExists(certificateLocation)) + if (!File.Exists(certificateLocation)) { return null; } @@ -1146,11 +1138,11 @@ namespace Emby.Server.Implementations return repo; } - private async Task<IActivityRepository> GetActivityLogRepositoryAsync() + private IActivityRepository GetActivityLogRepository() { - var repo = new ActivityRepository(ServerConfigurationManager.ApplicationPaths.DataPath); + var repo = new ActivityRepository(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager); - await repo.Database.EnsureCreatedAsync(); + repo.Initialize(); return repo; } @@ -1441,7 +1433,7 @@ namespace Emby.Server.Implementations //if (generateCertificate) //{ - // if (!FileSystemManager.FileExists(certPath)) + // if (!File.Exists(certPath)) // { // FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath)); @@ -1571,7 +1563,7 @@ namespace Emby.Server.Implementations /// <returns>IEnumerable{Assembly}.</returns> protected List<Tuple<Assembly, string>> GetComposablePartAssemblies() { - var list = GetPluginAssemblies(); + var list = GetPluginAssemblies(ApplicationPaths.PluginsPath); // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that // This will prevent the .dll file from getting locked, and allow us to replace it when needed @@ -1622,79 +1614,6 @@ namespace Emby.Server.Implementations protected abstract IEnumerable<Assembly> GetAssembliesWithPartsInternal(); - /// <summary> - /// Gets the plugin assemblies. - /// </summary> - /// <returns>IEnumerable{Assembly}.</returns> - private List<Tuple<Assembly, string>> GetPluginAssemblies() - { - // Copy pre-installed plugins - var sourcePath = Path.Combine(ApplicationPaths.ApplicationResourcesPath, "plugins"); - CopyPlugins(sourcePath, ApplicationPaths.PluginsPath); - - return GetPluginAssemblies(ApplicationPaths.PluginsPath); - } - - private void CopyPlugins(string source, string target) - { - List<string> files; - - try - { - files = Directory.EnumerateFiles(source, "*.dll", SearchOption.TopDirectoryOnly) - .ToList(); - - } - catch (DirectoryNotFoundException) - { - return; - } - - if (files.Count == 0) - { - return; - } - - foreach (var sourceFile in files) - { - var filename = Path.GetFileName(sourceFile); - var targetFile = Path.Combine(target, filename); - - var targetFileExists = File.Exists(targetFile); - - if (!targetFileExists && ServerConfigurationManager.Configuration.UninstalledPlugins.Contains(filename, StringComparer.OrdinalIgnoreCase)) - { - continue; - } - - if (targetFileExists && GetDllVersion(targetFile) >= GetDllVersion(sourceFile)) - { - continue; - } - - Directory.CreateDirectory(target); - File.Copy(sourceFile, targetFile, true); - } - } - - private Version GetDllVersion(string path) - { - try - { - var result = Version.Parse(FileVersionInfo.GetVersionInfo(path).FileVersion); - - Logger.LogInformation("File {Path} has version {Version}", path, result); - - return result; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error getting version number from {Path}", path); - - return new Version(1, 0); - } - } - private List<Tuple<Assembly, string>> GetPluginAssemblies(string path) { try diff --git a/Emby.Server.Implementations/Archiving/ZipClient.cs b/Emby.Server.Implementations/Archiving/ZipClient.cs index 84072cde6..1135cf694 100644 --- a/Emby.Server.Implementations/Archiving/ZipClient.cs +++ b/Emby.Server.Implementations/Archiving/ZipClient.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Archiving /// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param> public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = _fileSystem.OpenRead(sourceFile)) + using (var fileStream = File.OpenRead(sourceFile)) { ExtractAll(fileStream, targetPath, overwriteExistingFiles); } @@ -115,7 +115,7 @@ namespace Emby.Server.Implementations.Archiving /// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param> public void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = _fileSystem.OpenRead(sourceFile)) + using (var fileStream = File.OpenRead(sourceFile)) { ExtractAllFrom7z(fileStream, targetPath, overwriteExistingFiles); } @@ -155,7 +155,7 @@ namespace Emby.Server.Implementations.Archiving /// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param> public void ExtractAllFromTar(string sourceFile, string targetPath, bool overwriteExistingFiles) { - using (var fileStream = _fileSystem.OpenRead(sourceFile)) + using (var fileStream = File.OpenRead(sourceFile)) { ExtractAllFromTar(fileStream, targetPath, overwriteExistingFiles); } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index a306b0169..949b89226 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -355,7 +355,7 @@ namespace Emby.Server.Implementations.Channels return; } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(mediaSources, path); } @@ -834,7 +834,7 @@ namespace Emby.Server.Implementations.Channels { try { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(result, path); } diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 0166bbc5a..c8b822970 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.Collections return null; } - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); var libraryOptions = new LibraryOptions { @@ -133,7 +133,7 @@ namespace Emby.Server.Implementations.Collections try { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); var collection = new BoxSet { @@ -359,7 +359,7 @@ namespace Emby.Server.Implementations.Collections { var path = _collectionManager.GetCollectionsFolderPath(); - if (_fileSystem.DirectoryExists(path)) + if (Directory.Exists(path)) { try { diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index ab2e1c9a9..18e279c2f 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -148,7 +148,7 @@ namespace Emby.Server.Implementations.Configuration && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath)) { // Validate - if (!FileSystem.FileExists(newPath)) + if (!File.Exists(newPath)) { throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath)); } @@ -168,7 +168,7 @@ namespace Emby.Server.Implementations.Configuration && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath)) { // Validate - if (!FileSystem.DirectoryExists(newPath)) + if (!Directory.Exists(newPath)) { throw new FileNotFoundException(string.Format("{0} does not exist.", newPath)); } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 21294f96f..3de4da444 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -22,13 +22,10 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; using SQLitePCL.pretty; @@ -57,9 +54,6 @@ namespace Emby.Server.Implementations.Data /// The _app paths /// </summary> private readonly IServerConfigurationManager _config; - - private readonly IFileSystem _fileSystem; - private readonly IEnvironmentInfo _environmentInfo; private IServerApplicationHost _appHost; public IImageProcessor ImageProcessor { get; set; } @@ -72,16 +66,14 @@ namespace Emby.Server.Implementations.Data IServerApplicationHost appHost, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, - IAssemblyInfo assemblyInfo, - IFileSystem fileSystem, - IEnvironmentInfo environmentInfo, - ITimerFactory timerFactory) + IAssemblyInfo assemblyInfo) : base(loggerFactory.CreateLogger(nameof(SqliteItemRepository))) { if (config == null) { throw new ArgumentNullException(nameof(config)); } + if (jsonSerializer == null) { throw new ArgumentNullException(nameof(jsonSerializer)); @@ -90,8 +82,6 @@ namespace Emby.Server.Implementations.Data _appHost = appHost; _config = config; _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - _environmentInfo = environmentInfo; _typeMapper = new TypeMapper(assemblyInfo); DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); @@ -112,7 +102,7 @@ namespace Emby.Server.Implementations.Data { RunDefaultInitialization(connection); - var createMediaStreamsTableCommand + const string createMediaStreamsTableCommand = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -132,12 +122,11 @@ namespace Emby.Server.Implementations.Data "create index if not exists idxPeopleItemId1 on People(ItemId,ListOrder)", "create index if not exists idxPeopleName on People(Name)", - "create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", + "create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", createMediaStreamsTableCommand, "pragma shrink_memory" - }; connection.RunQueries(queries); @@ -219,6 +208,7 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "Width", "INT", existingColumnNames); AddColumn(db, "TypedBaseItems", "Height", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Size", "BIGINT", existingColumnNames); existingColumnNames = GetColumnNames(db, "ItemValues"); AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); @@ -247,7 +237,6 @@ namespace Emby.Server.Implementations.Data }, TransactionMode); string[] postQueries = - { // obsolete "drop index if exists idx_TypedBaseItems", @@ -325,14 +314,12 @@ namespace Emby.Server.Implementations.Data }; connection.RunQueries(postQueries); - - //await Vacuum(_connection).ConfigureAwait(false); } userDataRepo.Initialize(WriteLock, _connection, userManager); } - private readonly string[] _retriveItemColumns = + private static readonly string[] _retriveItemColumns = { "type", "data", @@ -361,6 +348,7 @@ namespace Emby.Server.Implementations.Data "OfficialRating", "ForcedSortName", "RunTimeTicks", + "Size", "DateCreated", "DateModified", "guid", @@ -402,7 +390,7 @@ namespace Emby.Server.Implementations.Data "OwnerId" }; - private readonly string[] _mediaStreamSaveColumns = + private static readonly string[] _mediaStreamSaveColumns = { "ItemId", "StreamIndex", @@ -443,7 +431,7 @@ namespace Emby.Server.Implementations.Data private static string GetSaveItemCommandText() { - var saveColumns = new List<string> + var saveColumns = new [] { "guid", "type", @@ -473,6 +461,7 @@ namespace Emby.Server.Implementations.Data "SortName", "ForcedSortName", "RunTimeTicks", + "Size", "DateCreated", "DateModified", "PreferredMetadataLanguage", @@ -520,11 +509,11 @@ namespace Emby.Server.Implementations.Data "OwnerId" }; - var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; + var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns) + ") values ("; - for (var i = 0; i < saveColumns.Count; i++) + for (var i = 0; i < saveColumns.Length; i++) { - if (i > 0) + if (i != 0) { saveItemCommandCommandText += ","; } @@ -628,44 +617,39 @@ namespace Emby.Server.Implementations.Data private void SaveItemsInTranscation(IDatabaseConnection db, List<Tuple<BaseItem, List<Guid>, BaseItem, string, List<string>>> tuples) { - var requiresReset = false; - var statements = PrepareAllSafe(db, new string[] { GetSaveItemCommandText(), "delete from AncestorIds where ItemId=@ItemId" - - }).ToList(); + }); using (var saveItemStatement = statements[0]) + using (var deleteAncestorsStatement = statements[1]) { - using (var deleteAncestorsStatement = statements[1]) + var requiresReset = false; + foreach (var tuple in tuples) { - foreach (var tuple in tuples) + if (requiresReset) { - if (requiresReset) - { - saveItemStatement.Reset(); - } + saveItemStatement.Reset(); + } - var item = tuple.Item1; - var topParent = tuple.Item3; - var userDataKey = tuple.Item4; + var item = tuple.Item1; + var topParent = tuple.Item3; + var userDataKey = tuple.Item4; - SaveItem(item, topParent, userDataKey, saveItemStatement); - //logger.LogDebug(_saveItemCommand.CommandText); + SaveItem(item, topParent, userDataKey, saveItemStatement); - var inheritedTags = tuple.Item5; + var inheritedTags = tuple.Item5; - if (item.SupportsAncestors) - { - UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); - } + if (item.SupportsAncestors) + { + UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); + } - UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); + UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); - requiresReset = true; - } + requiresReset = true; } } } @@ -701,8 +685,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@Path", GetPathToSave(item.Path)); - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) + if (item is IHasStartDate hasStartDate) { saveItemStatement.TryBind("@StartDate", hasStartDate.StartDate); } @@ -722,8 +705,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@ChannelId", item.ChannelId.Equals(Guid.Empty) ? null : item.ChannelId.ToString("N")); - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) + if (item is IHasProgramAttributes hasProgramAttributes) { saveItemStatement.TryBind("@IsMovie", hasProgramAttributes.IsMovie); saveItemStatement.TryBind("@IsSeries", hasProgramAttributes.IsSeries); @@ -776,6 +758,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName); saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks); + saveItemStatement.TryBind("@Size", item.Size); saveItemStatement.TryBind("@DateCreated", item.DateCreated); saveItemStatement.TryBind("@DateModified", item.DateModified); @@ -822,7 +805,7 @@ namespace Emby.Server.Implementations.Data if (item.LockedFields.Length > 0) { - saveItemStatement.TryBind("@LockedFields", string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray())); + saveItemStatement.TryBind("@LockedFields", string.Join("|", item.LockedFields)); } else { @@ -831,7 +814,7 @@ namespace Emby.Server.Implementations.Data if (item.Studios.Length > 0) { - saveItemStatement.TryBind("@Studios", string.Join("|", item.Studios.ToArray())); + saveItemStatement.TryBind("@Studios", string.Join("|", item.Studios)); } else { @@ -847,10 +830,9 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@Audio"); } - var livetvChannel = item as LiveTvChannel; - if (livetvChannel != null) + if (item is LiveTvChannel liveTvChannel) { - saveItemStatement.TryBind("@ExternalServiceId", livetvChannel.ServiceName); + saveItemStatement.TryBind("@ExternalServiceId", liveTvChannel.ServiceName); } else { @@ -870,21 +852,18 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@UnratedType", item.GetBlockUnratedType().ToString()); - if (topParent != null) + if (topParent == null) { - //logger.LogDebug("Item {0} has top parent {1}", item.Id, topParent.Id); - saveItemStatement.TryBind("@TopParentId", topParent.Id.ToString("N")); + saveItemStatement.TryBindNull("@TopParentId"); } else { - //logger.LogDebug("Item {0} has null top parent", item.Id); - saveItemStatement.TryBindNull("@TopParentId"); + saveItemStatement.TryBind("@TopParentId", topParent.Id.ToString("N")); } - var trailer = item as Trailer; - if (trailer != null && trailer.TrailerTypes.Length > 0) + if (item is Trailer trailer && trailer.TrailerTypes.Length > 0) { - saveItemStatement.TryBind("@TrailerTypes", string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray())); + saveItemStatement.TryBind("@TrailerTypes", string.Join("|", trailer.TrailerTypes)); } else { @@ -905,8 +884,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@PresentationUniqueKey", item.PresentationUniqueKey); saveItemStatement.TryBind("@OriginalTitle", item.OriginalTitle); - var video = item as Video; - if (video != null) + if (item is Video video) { saveItemStatement.TryBind("@PrimaryVersionId", video.PrimaryVersionId); } @@ -915,8 +893,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@PrimaryVersionId"); } - var folder = item as Folder; - if (folder != null && folder.DateLastMediaAdded.HasValue) + if (item is Folder folder && folder.DateLastMediaAdded.HasValue) { saveItemStatement.TryBind("@DateLastMediaAdded", folder.DateLastMediaAdded.Value); } @@ -928,8 +905,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@Album", item.Album); saveItemStatement.TryBind("@IsVirtualItem", item.IsVirtualItem); - var hasSeriesName = item as IHasSeries; - if (hasSeriesName != null) + if (item is IHasSeries hasSeriesName) { saveItemStatement.TryBind("@SeriesName", hasSeriesName.SeriesName); } @@ -937,7 +913,6 @@ namespace Emby.Server.Implementations.Data { saveItemStatement.TryBindNull("@SeriesName"); } - if (string.IsNullOrWhiteSpace(userDataKey)) { saveItemStatement.TryBindNull("@UserDataKey"); @@ -947,12 +922,11 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@UserDataKey", userDataKey); } - var episode = item as Episode; - if (episode != null) + if (item is Episode episode) { saveItemStatement.TryBind("@SeasonName", episode.SeasonName); - var nullableSeasonId = episode.SeasonId.Equals(Guid.Empty) ? (Guid?)null : episode.SeasonId; + var nullableSeasonId = episode.SeasonId == Guid.Empty ? (Guid?)null : episode.SeasonId; saveItemStatement.TryBind("@SeasonId", nullableSeasonId); } @@ -962,8 +936,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@SeasonId"); } - var hasSeries = item as IHasSeries; - if (hasSeries != null) + if (item is IHasSeries hasSeries) { var nullableSeriesId = hasSeries.SeriesId.Equals(Guid.Empty) ? (Guid?)null : hasSeries.SeriesId; @@ -1011,30 +984,22 @@ namespace Emby.Server.Implementations.Data } string artists = null; - var hasArtists = item as IHasArtist; - if (hasArtists != null) + if (item is IHasArtist hasArtists && hasArtists.Artists.Length > 0) { - if (hasArtists.Artists.Length > 0) - { - artists = string.Join("|", hasArtists.Artists); - } + artists = string.Join("|", hasArtists.Artists); } saveItemStatement.TryBind("@Artists", artists); string albumArtists = null; - var hasAlbumArtists = item as IHasAlbumArtist; - if (hasAlbumArtists != null) + if (item is IHasAlbumArtist hasAlbumArtists + && hasAlbumArtists.AlbumArtists.Length > 0) { - if (hasAlbumArtists.AlbumArtists.Length > 0) - { - albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists); - } + albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists); } saveItemStatement.TryBind("@AlbumArtists", albumArtists); saveItemStatement.TryBind("@ExternalId", item.ExternalId); - var program = item as LiveTvProgram; - if (program != null) + if (item is LiveTvProgram program) { saveItemStatement.TryBind("@ShowId", program.ShowId); } @@ -1043,14 +1008,14 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@ShowId"); } - var ownerId = item.OwnerId; - if (!ownerId.Equals(Guid.Empty)) + Guid ownerId = item.OwnerId; + if (ownerId == Guid.Empty) { - saveItemStatement.TryBind("@OwnerId", ownerId); + saveItemStatement.TryBindNull("@OwnerId"); } else { - saveItemStatement.TryBindNull("@OwnerId"); + saveItemStatement.TryBind("@OwnerId", ownerId); } saveItemStatement.MoveNext(); @@ -1058,17 +1023,24 @@ namespace Emby.Server.Implementations.Data private static string SerializeProviderIds(BaseItem item) { - // Ideally we shouldn't need this IsNullOrWhiteSpace check but we're seeing some cases of bad data slip through - var ids = item.ProviderIds - .Where(i => !string.IsNullOrWhiteSpace(i.Value)) - .ToList(); + StringBuilder str = new StringBuilder(); + foreach (var i in item.ProviderIds) + { + // Ideally we shouldn't need this IsNullOrWhiteSpace check, + // but we're seeing some cases of bad data slip through + if (string.IsNullOrWhiteSpace(i.Value)) + { + continue; + } + str.Append($"{i.Key}={i.Value}|"); + } - if (ids.Count == 0) + if (str.Length == 0) { return null; } - - return string.Join("|", ids.Select(i => i.Key + "=" + i.Value).ToArray()); + str.Length -= 1; // Remove last | + return str.ToString(); } private static void DeserializeProviderIds(string value, BaseItem item) @@ -1104,10 +1076,17 @@ namespace Emby.Server.Implementations.Data { return null; } - - var imageStrings = images.Where(i => !string.IsNullOrWhiteSpace(i.Path)).Select(ToValueString).ToArray(); - - return string.Join("|", imageStrings); + StringBuilder str = new StringBuilder(); + foreach (var i in images) + { + if (string.IsNullOrWhiteSpace(i.Path)) + { + continue; + } + str.Append(ToValueString(i) + "|"); + } + str.Length -= 1; // Remove last | + return str.ToString(); } private void DeserializeImages(string value, BaseItem item) @@ -1184,13 +1163,11 @@ namespace Emby.Server.Implementations.Data if (parts.Length >= 5) { - if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width)) + if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width) + && int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) { - if (int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) - { - image.Width = width; - image.Height = height; - } + image.Width = width; + image.Height = height; } } @@ -1212,7 +1189,7 @@ namespace Emby.Server.Implementations.Data } CheckDisposed(); - //logger.LogInformation("Retrieving item {0}", id.ToString("N")); + using (WriteLock.Read()) { using (var connection = CreateConnection(true)) @@ -1240,7 +1217,7 @@ namespace Emby.Server.Implementations.Data { return false; } - if (type == typeof(UserRootFolder)) + else if (type == typeof(UserRootFolder)) { return false; } @@ -1250,63 +1227,59 @@ namespace Emby.Server.Implementations.Data { return false; } - if (type == typeof(MusicArtist)) + else if (type == typeof(MusicArtist)) { return false; } - - if (type == typeof(Person)) + else if (type == typeof(Person)) { return false; } - if (type == typeof(MusicGenre)) + else if (type == typeof(MusicGenre)) { return false; } - if (type == typeof(GameGenre)) + else if (type == typeof(GameGenre)) { return false; } - if (type == typeof(Genre)) + else if (type == typeof(Genre)) { return false; } - if (type == typeof(Studio)) + else if (type == typeof(Studio)) { return false; } - if (type == typeof(PlaylistsFolder)) + else if (type == typeof(PlaylistsFolder)) { return false; } - - if (type == typeof(PhotoAlbum)) + else if (type == typeof(PhotoAlbum)) { return false; } - - if (type == typeof(Year)) + else if (type == typeof(Year)) { return false; } - if (type == typeof(Book)) + else if (type == typeof(Book)) { return false; } - if (type == typeof(LiveTvProgram)) + else if (type == typeof(LiveTvProgram)) { return false; } - if (type == typeof(AudioBook)) + else if (type == typeof(AudioBook)) { return false; } - - if (type == typeof(Audio)) + else if (type == typeof(Audio)) { return false; } - if (type == typeof(MusicAlbum)) + else if (type == typeof(MusicAlbum)) { return false; } @@ -1327,8 +1300,6 @@ namespace Emby.Server.Implementations.Data if (type == null) { - //logger.LogDebug("Unknown type {0}", typeString); - return null; } @@ -1373,8 +1344,7 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) + if (item is IHasStartDate hasStartDate) { hasStartDate.StartDate = reader[index].ReadDateTime(); } @@ -1396,8 +1366,7 @@ namespace Emby.Server.Implementations.Data if (enableProgramAttributes) { - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) + if (item is IHasProgramAttributes hasProgramAttributes) { if (!reader.IsDBNull(index)) { @@ -1558,6 +1527,12 @@ namespace Emby.Server.Implementations.Data } index++; + if (!reader.IsDBNull(index)) + { + item.Size = reader.GetInt64(index); + } + index++; + if (HasField(query, ItemFields.DateCreated)) { if (!reader.IsDBNull(index)) @@ -1604,12 +1579,11 @@ namespace Emby.Server.Implementations.Data // But get this excluded from contexts where it is not needed if (hasServiceName) { - var livetvChannel = item as LiveTvChannel; - if (livetvChannel != null) + if (item is LiveTvChannel liveTvChannel) { if (!reader.IsDBNull(index)) { - livetvChannel.ServiceName = reader.GetString(index); + liveTvChannel.ServiceName = reader.GetString(index); } } index++; @@ -1634,15 +1608,17 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - item.LockedFields = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select( - i => + IEnumerable<MetadataFields> GetLockedFields(string s) + { + foreach (var i in s.Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { if (Enum.TryParse(i, true, out MetadataFields parsedValue)) { - return parsedValue; + yield return parsedValue; } - return (MetadataFields?)null; - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); + } + } + item.LockedFields = GetLockedFields(reader.GetString(index)).ToArray(); } index++; } @@ -1667,21 +1643,21 @@ namespace Emby.Server.Implementations.Data if (hasTrailerTypes) { - var trailer = item as Trailer; - if (trailer != null) + if (item is Trailer trailer) { if (!reader.IsDBNull(index)) { - trailer.TrailerTypes = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select( - i => + IEnumerable<TrailerType> GetTrailerTypes(string s) + { + foreach (var i in s.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { if (Enum.TryParse(i, true, out TrailerType parsedValue)) { - return parsedValue; + yield return parsedValue; } - return (TrailerType?)null; - - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); + } + } + trailer.TrailerTypes = GetTrailerTypes(reader.GetString(index)).ToArray(); } } index++; @@ -1696,8 +1672,7 @@ namespace Emby.Server.Implementations.Data index++; } - var video = item as Video; - if (video != null) + if (item is Video video) { if (!reader.IsDBNull(index)) { @@ -1708,8 +1683,7 @@ namespace Emby.Server.Implementations.Data if (HasField(query, ItemFields.DateLastMediaAdded)) { - var folder = item as Folder; - if (folder != null && !reader.IsDBNull(index)) + if (item is Folder folder && !reader.IsDBNull(index)) { folder.DateLastMediaAdded = reader[index].TryReadDateTime(); } @@ -1734,8 +1708,7 @@ namespace Emby.Server.Implementations.Data } index++; - var hasSeriesName = item as IHasSeries; - if (hasSeriesName != null) + if (item is IHasSeries hasSeriesName) { if (!reader.IsDBNull(index)) { @@ -1746,8 +1719,7 @@ namespace Emby.Server.Implementations.Data if (hasEpisodeAttributes) { - var episode = item as Episode; - if (episode != null) + if (item is Episode episode) { if (!reader.IsDBNull(index)) { @@ -1834,7 +1806,7 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - item.ProductionLocations = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(); + item.ProductionLocations = reader.GetString(index).Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } index++; } @@ -1865,15 +1837,13 @@ namespace Emby.Server.Implementations.Data if (hasArtistFields) { - var hasArtists = item as IHasArtist; - if (hasArtists != null && !reader.IsDBNull(index)) + if (item is IHasArtist hasArtists && !reader.IsDBNull(index)) { hasArtists.Artists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } index++; - var hasAlbumArtists = item as IHasAlbumArtist; - if (hasAlbumArtists != null && !reader.IsDBNull(index)) + if (item is IHasAlbumArtist hasAlbumArtists && !reader.IsDBNull(index)) { hasAlbumArtists.AlbumArtists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } @@ -1900,19 +1870,11 @@ namespace Emby.Server.Implementations.Data if (enableProgramAttributes) { - var program = item as LiveTvProgram; - if (program != null) - { - if (!reader.IsDBNull(index)) - { - program.ShowId = reader.GetString(index); - } - index++; - } - else + if (item is LiveTvProgram program && !reader.IsDBNull(index)) { - index++; + program.ShowId = reader.GetString(index); } + index++; } if (!reader.IsDBNull(index)) @@ -2080,18 +2042,12 @@ namespace Emby.Server.Implementations.Data var insertText = new StringBuilder("insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values "); var endIndex = Math.Min(chapters.Count, startIndex + limit); - var isSubsequentRow = false; for (var i = startIndex; i < endIndex; i++) { - if (isSubsequentRow) - { - insertText.Append(","); - } - - insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0})", i.ToString(CultureInfo.InvariantCulture)); - isSubsequentRow = true; + insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture)); } + insertText.Length -= 1; // Remove last , using (var statement = PrepareStatementSafe(db, insertText.ToString())) { @@ -2127,59 +2083,19 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = query.OrderBy.Select(i => i.Item1).ToList(); + var sortingFields = query.OrderBy.Select(i => i.Item1); - if (sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - - if (query.IsFavoriteOrLiked.HasValue) - { - return true; - } - - if (query.IsFavorite.HasValue) - { - return true; - } - - if (query.IsResumable.HasValue) - { - return true; - } - - if (query.IsPlayed.HasValue) - { - return true; - } - - if (query.IsLiked.HasValue) - { - return true; - } - - return false; + return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase) + || query.IsFavoriteOrLiked.HasValue + || query.IsFavorite.HasValue + || query.IsResumable.HasValue + || query.IsPlayed.HasValue + || query.IsLiked.HasValue; } private readonly List<ItemFields> allFields = Enum.GetNames(typeof(ItemFields)) @@ -2188,32 +2104,23 @@ namespace Emby.Server.Implementations.Data private string[] GetColumnNamesFromField(ItemFields field) { - if (field == ItemFields.Settings) - { - return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; - } - if (field == ItemFields.ServiceName) - { - return new[] { "ExternalServiceId" }; - } - if (field == ItemFields.SortName) - { - return new[] { "ForcedSortName" }; - } - if (field == ItemFields.Taglines) - { - return new[] { "Tagline" }; - } - if (field == ItemFields.Tags) - { - return new[] { "Tags" }; - } - if (field == ItemFields.IsHD) + switch (field) { - return Array.Empty<string>(); + case ItemFields.Settings: + return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; + case ItemFields.ServiceName: + return new[] { "ExternalServiceId" }; + case ItemFields.SortName: + return new[] { "ForcedSortName" }; + case ItemFields.Taglines: + return new[] { "Tagline" }; + case ItemFields.Tags: + return new[] { "Tags" }; + case ItemFields.IsHD: + return Array.Empty<string>(); + default: + return new[] { field.ToString() }; } - - return new[] { field.ToString() }; } private bool HasField(InternalItemsQuery query, ItemFields name) @@ -2347,12 +2254,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Episode" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Contains("Episode", StringComparer.OrdinalIgnoreCase); } private bool HasTrailerTypes(InternalItemsQuery query) @@ -2362,12 +2264,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Trailer" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase); } private bool HasArtistFields(InternalItemsQuery query) @@ -2403,12 +2300,7 @@ namespace Emby.Server.Implementations.Data private bool HasSeriesFields(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (string.Equals(query.ParentType, "PhotoAlbum", StringComparison.OrdinalIgnoreCase)) { return false; } @@ -2520,7 +2412,6 @@ namespace Emby.Server.Implementations.Data if (item.ProductionYear.HasValue) { - //builder.Append("+ ((ProductionYear=@ItemProductionYear) * 10)"); builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 10 Else 0 End )"); builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 5 Else 0 End )"); } @@ -2528,12 +2419,6 @@ namespace Emby.Server.Implementations.Data //// genres, tags builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId)) * 10)"); - //builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=3 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=3)) * 3)"); - - //builder.Append("+ ((Select count(Name) from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId)) * 3)"); - - ////builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); - builder.Append(") as SimilarityScore"); list.Add(builder.ToString()); @@ -2642,7 +2527,7 @@ namespace Emby.Server.Implementations.Data if (groups.Count > 0) { - return " Group by " + string.Join(",", groups.ToArray()); + return " Group by " + string.Join(",", groups); } return string.Empty; @@ -2662,8 +2547,6 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); - //logger.LogInformation("GetItemList: " + _environmentInfo.StackTrace); - var now = DateTime.UtcNow; // Hack for right now since we currently don't support filtering out these duplicates within a query @@ -2672,18 +2555,16 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - //commandText += GetGroupBy(query); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } using (WriteLock.Read()) { @@ -2720,8 +2601,6 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); - //logger.LogInformation("GetItemList: " + _environmentInfo.StackTrace); - var now = DateTime.UtcNow; // Hack for right now since we currently don't support filtering out these duplicates within a query @@ -2730,20 +2609,20 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -2878,25 +2757,18 @@ namespace Emby.Server.Implementations.Data { var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - var slowThreshold = 1000; + int slowThreshold = 1000; #if DEBUG - slowThreshold = 10; + slowThreshold = 250; #endif if (elapsed >= slowThreshold) { - Logger.LogDebug("{2} query time (slow): {0}ms. Query: {1}", - Convert.ToInt32(elapsed), - commandText, - methodName); - } - else - { - //logger.LogDebug("{2} query time: {0}ms. Query: {1}", - // Convert.ToInt32(elapsed), - // commandText, - // methodName); + Logger.LogWarning("{0} query time (slow): {1}ms. Query: {2}", + methodName, + elapsed, + commandText); } } @@ -2918,7 +2790,6 @@ namespace Emby.Server.Implementations.Data TotalRecordCount = returnList.Count }; } - //logger.LogInformation("GetItems: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; @@ -2930,8 +2801,10 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); @@ -2939,13 +2812,9 @@ namespace Emby.Server.Implementations.Data string.Empty : " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereTextWithoutPaging = whereText; - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += whereText + + GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -2986,8 +2855,8 @@ namespace Emby.Server.Implementations.Data commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } - commandText += GetJoinUserDataText(query); - commandText += whereTextWithoutPaging; + commandText += GetJoinUserDataText(query) + + whereText; statementTexts.Add(commandText); } @@ -3068,14 +2937,10 @@ namespace Emby.Server.Implementations.Data var orderBy = query.OrderBy.ToList(); var enableOrderInversion = false; - if (query.SimilarTo != null) + if (query.SimilarTo != null && orderBy.Count == 0) { - if (orderBy.Count == 0) - { - orderBy.Add(new ValueTuple<string, SortOrder>("SimilarityScore", SortOrder.Descending)); - orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); - //orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); - } + orderBy.Add(new ValueTuple<string, SortOrder>("SimilarityScore", SortOrder.Descending)); + orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); } if (!string.IsNullOrEmpty(query.SearchTerm)) @@ -3104,7 +2969,7 @@ namespace Emby.Server.Implementations.Data var sortOrder = columnAscending ? "ASC" : "DESC"; return columnMap.Item1 + " " + sortOrder; - }).ToArray()); + })); } private ValueTuple<string, bool> MapOrderByField(string name, InternalItemsQuery query) @@ -3112,76 +2977,75 @@ namespace Emby.Server.Implementations.Data if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { // TODO - return new ValueTuple<string, bool>("SortName", false); + return ("SortName", false); } - if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("RuntimeTicks", false); + return ("RuntimeTicks", false); } - if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("RANDOM()", false); + return ("RANDOM()", false); } - if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) { if (query.GroupBySeriesPresentationUniqueKey) { - return new ValueTuple<string, bool>("MAX(LastPlayedDate)", false); + return ("MAX(LastPlayedDate)", false); } - return new ValueTuple<string, bool>("LastPlayedDate", false); + return ("LastPlayedDate", false); } - if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("PlayCount", false); + return ("PlayCount", false); } - if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) { - // (Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 2 Else 0 End ) - return new ValueTuple<string, bool>("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); + return ("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); } - if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("IsFolder", true); + return ("IsFolder", true); } - if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("played", true); + return ("played", true); } - if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("played", false); + return ("played", false); } - if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("DateLastMediaAdded", false); + return ("DateLastMediaAdded", false); } - if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("InheritedParentalRatingValue", false); + return ("InheritedParentalRatingValue", false); } - if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); + return ("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); } - if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("SeriesName", false); + return ("SeriesName", false); } - return new ValueTuple<string, bool>(name, false); + return (name, false); } public List<Guid> GetItemIdsList(InternalItemsQuery query) @@ -3192,24 +3056,22 @@ namespace Emby.Server.Implementations.Data } CheckDisposed(); - //logger.LogInformation("GetItemIdsList: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3272,16 +3134,13 @@ namespace Emby.Server.Implementations.Data var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid", "path" })) + GetFromText(); var whereClauses = GetWhereClauses(query, null); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3298,10 +3157,9 @@ namespace Emby.Server.Implementations.Data } } - var list = new List<Tuple<Guid, string>>(); - using (WriteLock.Read()) { + var list = new List<Tuple<Guid, string>>(); using (var connection = CreateConnection(true)) { using (var statement = PrepareStatementSafe(connection, commandText)) @@ -3352,12 +3210,13 @@ namespace Emby.Server.Implementations.Data TotalRecordCount = returnList.Count }; } - //logger.LogInformation("GetItemIds: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); @@ -3365,13 +3224,9 @@ namespace Emby.Server.Implementations.Data string.Empty : " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereTextWithoutPaging = whereText; - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += whereText + + GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3413,8 +3268,8 @@ namespace Emby.Server.Implementations.Data commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } - commandText += GetJoinUserDataText(query); - commandText += whereTextWithoutPaging; + commandText += GetJoinUserDataText(query) + + whereText; statementTexts.Add(commandText); } @@ -3482,12 +3337,16 @@ namespace Emby.Server.Implementations.Data private bool IsAlphaNumeric(string str) { if (string.IsNullOrWhiteSpace(str)) + { return false; + } for (int i = 0; i < str.Length; i++) { if (!(char.IsLetter(str[i])) && (!(char.IsNumber(str[i])))) + { return false; + } } return true; @@ -3503,11 +3362,6 @@ namespace Emby.Server.Implementations.Data return IsAlphaNumeric(value); } - private bool IsValidId(string value) - { - return IsAlphaNumeric(value); - } - private bool IsValidPersonType(string value) { return IsAlphaNumeric(value); @@ -3520,13 +3374,6 @@ namespace Emby.Server.Implementations.Data query.IsVirtualItem = false; } - var whereClauses = new List<string>(); - - if (EnableJoinUserData(query)) - { - //whereClauses.Add("(UserId is null or UserId=@UserId)"); - } - var minWidth = query.MinWidth; var maxWidth = query.MaxWidth; @@ -3556,6 +3403,8 @@ namespace Emby.Server.Implementations.Data } } + var whereClauses = new List<string>(); + if (minWidth.HasValue) { whereClauses.Add("Width>=@MinWidth"); @@ -3601,47 +3450,8 @@ namespace Emby.Server.Implementations.Data var tags = query.Tags.ToList(); var excludeTags = query.ExcludeTags.ToList(); - //if (!(query.IsMovie ?? true) || !(query.IsSeries ?? true)) - //{ - // if (query.IsMovie.HasValue) - // { - // var alternateTypes = new List<string>(); - // if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) - // { - // alternateTypes.Add(typeof(Movie).FullName); - // } - // if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name)) - // { - // alternateTypes.Add(typeof(Trailer).FullName); - // } - - // if (alternateTypes.Count == 0) - // { - // whereClauses.Add("IsMovie=@IsMovie"); - // if (statement != null) - // { - // statement.TryBind("@IsMovie", query.IsMovie); - // } - // } - // else - // { - // whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); - // if (statement != null) - // { - // statement.TryBind("@IsMovie", query.IsMovie); - // } - // } - // } - //} - //else - //{ - - //} - if (query.IsMovie ?? false) { - var programAttribtues = new List<string>(); - var alternateTypes = new List<string>(); if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) { @@ -3652,6 +3462,7 @@ namespace Emby.Server.Implementations.Data alternateTypes.Add(typeof(Trailer).FullName); } + var programAttribtues = new List<string>(); if (alternateTypes.Count == 0) { programAttribtues.Add("IsMovie=@IsMovie"); @@ -3666,7 +3477,7 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@IsMovie", true); } - whereClauses.Add("(" + string.Join(" OR ", programAttribtues.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", programAttribtues) + ")"); } else if (query.IsMovie.HasValue) { @@ -3752,8 +3563,8 @@ namespace Emby.Server.Implementations.Data } else if (includeTypes.Length > 1) { - var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type in ({0})", inClause)); + var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'")); + whereClauses.Add($"type in ({inClause})"); } // Only specify excluded types if no included types are specified @@ -3770,8 +3581,8 @@ namespace Emby.Server.Implementations.Data } else if (excludeTypes.Length > 1) { - var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type not in ({0})", inClause)); + var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'")); + whereClauses.Add($"type not in ({inClause})"); } } @@ -3785,8 +3596,8 @@ namespace Emby.Server.Implementations.Data } else if (query.ChannelIds.Length > 1) { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); - whereClauses.Add(string.Format("ChannelId in ({0})", inClause)); + var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N") + "'")); + whereClauses.Add($"ChannelId in ({inClause})"); } if (!query.ParentId.Equals(Guid.Empty)) @@ -3800,7 +3611,6 @@ namespace Emby.Server.Implementations.Data if (!string.IsNullOrWhiteSpace(query.Path)) { - //whereClauses.Add("(Path=@Path COLLATE NOCASE)"); whereClauses.Add("Path=@Path"); if (statement != null) { @@ -3862,18 +3672,6 @@ namespace Emby.Server.Implementations.Data } } - //if (query.MinPlayers.HasValue) - //{ - // whereClauses.Add("Players>=@MinPlayers"); - // cmd.Parameters.Add(cmd, "@MinPlayers", DbType.Int32).Value = query.MinPlayers.Value; - //} - - //if (query.MaxPlayers.HasValue) - //{ - // whereClauses.Add("Players<=@MaxPlayers"); - // cmd.Parameters.Add(cmd, "@MaxPlayers", DbType.Int32).Value = query.MaxPlayers.Value; - //} - if (query.IndexNumber.HasValue) { whereClauses.Add("IndexNumber=@IndexNumber"); @@ -3982,7 +3780,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4030,7 +3828,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4241,7 +4039,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4260,7 +4058,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4279,7 +4077,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4298,7 +4096,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4317,7 +4115,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4336,7 +4134,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4353,7 +4151,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4370,7 +4168,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4387,7 +4185,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4407,7 +4205,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4424,7 +4222,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4631,7 +4429,7 @@ namespace Emby.Server.Implementations.Data } else if (queryMediaTypes.Length > 1) { - var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'")); whereClauses.Add("MediaType in (" + val + ")"); } @@ -4650,7 +4448,7 @@ namespace Emby.Server.Implementations.Data index++; } - whereClauses.Add("(" + string.Join(" OR ", includeIds.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", includeIds) + ")"); } if (query.ExcludeItemIds.Length > 0) { @@ -4667,7 +4465,7 @@ namespace Emby.Server.Implementations.Data index++; } - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + whereClauses.Add(string.Join(" AND ", excludeIds)); } if (query.ExcludeProviderIds.Count > 0) @@ -4683,7 +4481,6 @@ namespace Emby.Server.Implementations.Data } var paramName = "@ExcludeProviderId" + index; - //excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); excludeIds.Add("(ProviderIds is null or ProviderIds not like " + paramName + ")"); if (statement != null) { @@ -4696,7 +4493,7 @@ namespace Emby.Server.Implementations.Data if (excludeIds.Count > 0) { - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + whereClauses.Add(string.Join(" AND ", excludeIds)); } } @@ -4738,7 +4535,7 @@ namespace Emby.Server.Implementations.Data if (hasProviderIds.Count > 0) { - whereClauses.Add("(" + string.Join(" OR ", hasProviderIds.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", hasProviderIds) + ")"); } } @@ -4774,7 +4571,7 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'").ToArray()); + var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(TopParentId=@TopParentId or Type in (" + itemByNameTypeVal + "))"); } else @@ -4788,7 +4585,7 @@ namespace Emby.Server.Implementations.Data } else if (queryTopParentIds.Length > 1) { - var val = string.Join(",", queryTopParentIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); + var val = string.Join(",", queryTopParentIds.Select(i => "'" + i.ToString("N") + "'")); if (enableItemsByName && includedItemByNameTypes.Count == 1) { @@ -4800,12 +4597,12 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'").ToArray()); + var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(Type in (" + itemByNameTypeVal + ") or TopParentId in (" + val + "))"); } else { - whereClauses.Add("(TopParentId in (" + val + "))"); + whereClauses.Add("TopParentId in (" + val + ")"); } } @@ -4820,7 +4617,7 @@ namespace Emby.Server.Implementations.Data } if (query.AncestorIds.Length > 1) { - var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); + var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N") + "'")); whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) @@ -4853,13 +4650,13 @@ namespace Emby.Server.Implementations.Data } if (query.BlockUnratedItems.Length > 1) { - var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'").ToArray()); + var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'")); whereClauses.Add(string.Format("(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", inClause)); } if (query.ExcludeInheritedTags.Length > 0) { - var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'").ToArray(); + var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'"); var tagValuesList = string.Join(",", tagValues); whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)"); @@ -4874,7 +4671,7 @@ namespace Emby.Server.Implementations.Data statuses.Add("data like '%" + seriesStatus + "%'"); } - whereClauses.Add("(" + string.Join(" OR ", statuses.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", statuses) + ")"); } if (query.BoxSetLibraryFolders.Length > 0) @@ -4886,7 +4683,7 @@ namespace Emby.Server.Implementations.Data folderIdQueries.Add("data like '%" + folderId.ToString("N") + "%'"); } - whereClauses.Add("(" + string.Join(" OR ", folderIdQueries.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", folderIdQueries) + ")"); } if (query.VideoTypes.Length > 0) @@ -4898,7 +4695,7 @@ namespace Emby.Server.Implementations.Data videoTypes.Add("data like '%\"VideoType\":\"" + videoType.ToString() + "\"%'"); } - whereClauses.Add("(" + string.Join(" OR ", videoTypes.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", videoTypes) + ")"); } if (query.Is3D.HasValue) @@ -5055,13 +4852,15 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new[] { + var types = new[] + { typeof(Episode).Name, - typeof(Video).Name , - typeof(Movie).Name , - typeof(MusicVideo).Name , - typeof(Series).Name , - typeof(Season).Name }; + typeof(Video).Name, + typeof(Movie).Name, + typeof(MusicVideo).Name, + typeof(Series).Name, + typeof(Season).Name + }; if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase))) { @@ -5169,7 +4968,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public void DeleteItem(Guid id, CancellationToken cancellationToken) { - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { throw new ArgumentNullException(nameof(id)); } @@ -5229,9 +5028,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var whereClauses = GetPeopleWhereClauses(query, null); - if (whereClauses.Count > 0) + if (whereClauses.Count != 0) { - commandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + commandText += " where " + string.Join(" AND ", whereClauses); } commandText += " order by ListOrder"; @@ -5269,9 +5068,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var whereClauses = GetPeopleWhereClauses(query, null); - if (whereClauses.Count > 0) + if (whereClauses.Count != 0) { - commandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + commandText += " where " + string.Join(" AND ", whereClauses); } commandText += " order by ListOrder"; @@ -5330,7 +5129,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } else if (queryPersonTypes.Count > 1) { - var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType in (" + val + ")"); } @@ -5346,7 +5145,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } else if (queryExcludePersonTypes.Count > 1) { - var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType not in (" + val + ")"); } @@ -5498,18 +5297,18 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeClause = itemValueTypes.Length == 1 ? ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")"); + ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); var commandText = "Select Value From ItemValues where " + typeClause; if (withItemTypes.Count > 0) { - var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'").ToArray()); + var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))"; } if (excludeItemTypes.Count > 0) { - var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'").ToArray()); + var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId not In (select guid from typedbaseitems where type in (" + typeString + "))"; } @@ -5552,7 +5351,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } CheckDisposed(); - //logger.LogInformation("GetItemValues: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; @@ -5562,7 +5360,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type InternalItemsQuery typeSubQuery = null; - var itemCountColumns = new List<Tuple<string, string>>(); + Dictionary<string, string> itemCountColumns = null; var typesToCount = query.IncludeItemTypes; @@ -5588,17 +5386,21 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeWhereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses); itemCountColumnQuery += typeWhereText; - //itemCountColumnQuery += ")"; - - itemCountColumns.Add(new Tuple<string, string>("itemTypes", "(" + itemCountColumnQuery + ") as itemTypes")); + itemCountColumns = new Dictionary<string, string>() + { + { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes"} + }; } - var columns = _retriveItemColumns.ToList(); - columns.AddRange(itemCountColumns.Select(i => i.Item2).ToArray()); + List<string> columns = _retriveItemColumns.ToList(); + if (itemCountColumns != null) + { + columns.AddRange(itemCountColumns.Values); + } // do this first before calling GetFinalColumnsToSelect, otherwise ExcludeItemIds will be set by SimilarTo var innerQuery = new InternalItemsQuery(query.User) @@ -5621,26 +5423,18 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type columns = GetFinalColumnsToSelect(query, columns.ToArray()).ToList(); - var commandText = "select " + string.Join(",", columns.ToArray()) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", columns) + + GetFromText() + + GetJoinUserDataText(query); var innerWhereClauses = GetWhereClauses(innerQuery, null); var innerWhereText = innerWhereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", innerWhereClauses.ToArray()); + " where " + string.Join(" AND ", innerWhereClauses); - var whereText = " where Type=@SelectType"; - - if (typesToCount.Length == 0) - { - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } - else - { - //whereText += " And itemTypes not null"; - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } + var whereText = " where Type=@SelectType And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; var outerQuery = new InternalItemsQuery(query.User) { @@ -5664,13 +5458,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var outerWhereClauses = GetWhereClauses(outerQuery, null); - whereText += outerWhereClauses.Count == 0 ? - string.Empty : - " AND " + string.Join(" AND ", outerWhereClauses.ToArray()); - //cmd.CommandText += GetGroupBy(query); + if (outerWhereClauses.Count != 0) + { + whereText += " AND " + string.Join(" AND ", outerWhereClauses); + } - commandText += whereText; - commandText += " group by PresentationUniqueKey"; + commandText += whereText + " group by PresentationUniqueKey"; if (query.SimilarTo != null || !string.IsNullOrEmpty(query.SearchTerm)) { @@ -5705,10 +5498,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } if (query.EnableTotalRecordCount) { - var countText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); + var countText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query) + + whereText; - countText += GetJoinUserDataText(query); - countText += whereText; statementTexts.Add(countText); } @@ -5721,7 +5516,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var list = new List<Tuple<BaseItem, ItemCounts>>(); var result = new QueryResult<Tuple<BaseItem, ItemCounts>>(); - //logger.LogInformation("GetItemValues {0}", string.Join(";", statementTexts.ToArray())); var statements = PrepareAllSafe(db, statementTexts); if (!isReturningZeroItems) @@ -5768,10 +5562,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type if (query.EnableTotalRecordCount) { - commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); - - commandText += GetJoinUserDataText(query); - commandText += whereText; + commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query) + + whereText; using (var statement = statements[statements.Count - 1]) { @@ -5826,11 +5621,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } var allTypes = typeString.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) - .ToLookup(i => i).ToList(); + .ToLookup(i => i); foreach (var type in allTypes) { - var value = type.ToList().Count; + var value = type.Count(); var typeName = type.Key; if (string.Equals(typeName, typeof(Series).FullName, StringComparison.OrdinalIgnoreCase)) @@ -5875,14 +5670,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { var list = new List<Tuple<int, string>>(); - var hasArtist = item as IHasArtist; - if (hasArtist != null) + if (item is IHasArtist hasArtist) { list.AddRange(hasArtist.Artists.Select(i => new Tuple<int, string>(0, i))); } - var hasAlbumArtist = item as IHasAlbumArtist; - if (hasAlbumArtist != null) + if (item is IHasAlbumArtist hasAlbumArtist) { list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple<int, string>(1, i))); } @@ -6092,9 +5885,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type throw new ArgumentNullException(nameof(query)); } - var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; - - cmdText += " ItemId=@ItemId"; + var cmdText = "select " + + string.Join(",", _mediaStreamSaveColumns) + + " from mediastreams where" + + " ItemId=@ItemId"; if (query.Type.HasValue) { @@ -6143,7 +5937,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { CheckDisposed(); - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { throw new ArgumentNullException(nameof(id)); } @@ -6183,21 +5977,24 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var insertText = new StringBuilder(string.Format("insert into mediastreams ({0}) values ", string.Join(",", _mediaStreamSaveColumns))); var endIndex = Math.Min(streams.Count, startIndex + limit); - var isSubsequentRow = false; for (var i = startIndex; i < endIndex; i++) { - if (isSubsequentRow) + if (i != startIndex) { insertText.Append(","); } var index = i.ToString(CultureInfo.InvariantCulture); + insertText.Append("(@ItemId, "); - var mediaStreamSaveColumns = string.Join(",", _mediaStreamSaveColumns.Skip(1).Select(m => "@" + m + index).ToArray()); + foreach (var column in _mediaStreamSaveColumns.Skip(1)) + { + insertText.Append("@" + column + index + ","); + } + insertText.Length -= 1; // Remove the last comma - insertText.AppendFormat("(@ItemId, {0})", mediaStreamSaveColumns); - isSubsequentRow = true; + insertText.Append(")"); } using (var statement = PrepareStatementSafe(db, insertText.ToString())) diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index 00761809a..866bd137f 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -53,11 +53,11 @@ namespace Emby.Server.Implementations.Devices { var path = CachePath; - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_syncLock) { - _fileSystem.WriteAllText(path, id, Encoding.UTF8); + File.WriteAllText(path, id, Encoding.UTF8); } } catch (Exception ex) diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index 60d57519e..e94a649bf 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.Devices public void SaveCapabilities(string deviceId, ClientCapabilities capabilities) { var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_capabilitiesSyncLock) { @@ -239,7 +239,7 @@ namespace Emby.Server.Implementations.Devices path = Path.Combine(path, file.Name); path = Path.ChangeExtension(path, MimeTypes.ToExtension(file.MimeType) ?? "jpg"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); await EnsureLibraryFolder(uploadPathInfo.Item2, uploadPathInfo.Item3).ConfigureAwait(false); @@ -275,7 +275,7 @@ namespace Emby.Server.Implementations.Devices private void AddCameraUpload(string deviceId, LocalFileInfo file) { var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_cameraUploadSyncLock) { @@ -317,7 +317,7 @@ namespace Emby.Server.Implementations.Devices return Task.CompletedTask; } - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); var libraryOptions = new LibraryOptions { @@ -431,7 +431,7 @@ namespace Emby.Server.Implementations.Devices { var path = _deviceManager.GetUploadsPath(); - if (_fileSystem.DirectoryExists(path)) + if (Directory.Exists(path)) { try { diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 13febc214..d0a7de11d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1428,7 +1428,7 @@ namespace Emby.Server.Implementations.Dto var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary); - ImageSize size; + ImageDimensions size; var defaultAspectRatio = item.GetDefaultPrimaryImageAspectRatio(); @@ -1439,9 +1439,9 @@ namespace Emby.Server.Implementations.Dto return defaultAspectRatio; } - double dummyWidth = 200; - double dummyHeight = dummyWidth / defaultAspectRatio; - size = new ImageSize(dummyWidth, dummyHeight); + int dummyWidth = 200; + int dummyHeight = Convert.ToInt32(dummyWidth / defaultAspectRatio); + size = new ImageDimensions(dummyWidth, dummyHeight); } else { @@ -1481,7 +1481,7 @@ namespace Emby.Server.Implementations.Dto var width = size.Width; var height = size.Height; - if (width.Equals(0) || height.Equals(0)) + if (width <= 0 || height <= 0) { return null; } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f2a5b2e38..3aa617b02 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -22,7 +22,6 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.0" /> <PackageReference Include="ServiceStack.Text.Core" Version="5.4.0" /> <PackageReference Include="sharpcompress" Version="0.22.0" /> <PackageReference Include="SimpleInjector" Version="4.4.2" /> diff --git a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs deleted file mode 100644 index 72c8acd9f..000000000 --- a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.System; - -namespace Emby.Server.Implementations.EntryPoints -{ - public class SystemEvents : IServerEntryPoint - { - private readonly ISystemEvents _systemEvents; - private readonly IServerApplicationHost _appHost; - - public SystemEvents(ISystemEvents systemEvents, IServerApplicationHost appHost) - { - _systemEvents = systemEvents; - _appHost = appHost; - } - - public void Run() - { - _systemEvents.SystemShutdown += _systemEvents_SystemShutdown; - } - - private void _systemEvents_SystemShutdown(object sender, EventArgs e) - { - _appHost.Shutdown(); - } - - public void Dispose() - { - _systemEvents.SystemShutdown -= _systemEvents_SystemShutdown; - } - } -} diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs index 9a4aec958..79a42f294 100644 --- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs +++ b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs @@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.FFMpeg var prebuiltFolder = _appPaths.ProgramSystemPath; var prebuiltffmpeg = Path.Combine(prebuiltFolder, downloadInfo.FFMpegFilename); var prebuiltffprobe = Path.Combine(prebuiltFolder, downloadInfo.FFProbeFilename); - if (_fileSystem.FileExists(prebuiltffmpeg) && _fileSystem.FileExists(prebuiltffprobe)) + if (File.Exists(prebuiltffmpeg) && File.Exists(prebuiltffprobe)) { return new FFMpegInfo { @@ -75,11 +75,11 @@ namespace Emby.Server.Implementations.FFMpeg Version = version }; - _fileSystem.CreateDirectory(versionedDirectoryPath); + Directory.CreateDirectory(versionedDirectoryPath); var excludeFromDeletions = new List<string> { versionedDirectoryPath }; - if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) + if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath)) { // ffmpeg not present. See if there's an older version we can start with var existingVersion = GetExistingVersion(info, rootEncoderPath); @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.FFMpeg else { info = existingVersion; - versionedDirectoryPath = _fileSystem.GetDirectoryName(info.EncoderPath); + versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath); excludeFromDeletions.Add(versionedDirectoryPath); } } @@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.FFMpeg { EncoderPath = encoder, ProbePath = probe, - Version = Path.GetFileName(_fileSystem.GetDirectoryName(probe)) + Version = Path.GetFileName(Path.GetDirectoryName(probe)) }; } } diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index ea620cb2e..a61247fd1 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -286,28 +286,18 @@ namespace Emby.Server.Implementations.HttpClientManager private HttpResponseInfo GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url) { - try - { - if (_fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow) - { - var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true); - - return new HttpResponseInfo - { - ResponseUrl = url, - Content = stream, - StatusCode = HttpStatusCode.OK, - ContentLength = stream.Length - }; - } - } - catch (FileNotFoundException) // REVIEW: @bond Is this really faster? - { - - } - catch (DirectoryNotFoundException) + if (File.Exists(responseCachePath) + && _fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow) { + var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true); + return new HttpResponseInfo + { + ResponseUrl = url, + Content = stream, + StatusCode = HttpStatusCode.OK, + ContentLength = stream.Length + }; } return null; @@ -315,7 +305,7 @@ namespace Emby.Server.Implementations.HttpClientManager private async Task CacheResponse(HttpResponseInfo response, string responseCachePath) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath)); + Directory.CreateDirectory(Path.GetDirectoryName(responseCachePath)); using (var fileStream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true)) { @@ -523,7 +513,7 @@ namespace Emby.Server.Implementations.HttpClientManager { ValidateParams(options); - _fileSystem.CreateDirectory(_appPaths.TempDirectory); + Directory.CreateDirectory(_appPaths.TempDirectory); var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp"); diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 6bee178ea..12532a497 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -189,13 +189,13 @@ namespace Emby.Server.Implementations.IO { item = LibraryManager.FindByPath(path, null); - path = _fileSystem.GetDirectoryName(path); + path = System.IO.Path.GetDirectoryName(path); } if (item != null) { // If the item has been deleted find the first valid parent that still exists - while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) + while (!Directory.Exists(item.Path) && !File.Exists(item.Path)) { item = item.GetOwner() ?? item.GetParent(); diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 6a3204011..dad81c195 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -140,7 +140,14 @@ namespace Emby.Server.Implementations.IO /// <summary> /// Initializes a new instance of the <see cref="LibraryMonitor" /> class. /// </summary> - public LibraryMonitor(ILoggerFactory loggerFactory, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents, IEnvironmentInfo environmentInfo) + public LibraryMonitor( + ILoggerFactory loggerFactory, + ITaskManager taskManager, + ILibraryManager libraryManager, + IServerConfigurationManager configurationManager, + IFileSystem fileSystem, + ITimerFactory timerFactory, + IEnvironmentInfo environmentInfo) { if (taskManager == null) { @@ -154,26 +161,9 @@ namespace Emby.Server.Implementations.IO _fileSystem = fileSystem; _timerFactory = timerFactory; _environmentInfo = environmentInfo; - - systemEvents.Resume += _systemEvents_Resume; - } - - private void _systemEvents_Resume(object sender, EventArgs e) - { - Restart(); - } - - private void Restart() - { - Stop(); - - if (!_disposed) - { - Start(); - } } - private bool IsLibraryMonitorEnabaled(BaseItem item) + private bool IsLibraryMonitorEnabled(BaseItem item) { if (item is BasePluginFolder) { @@ -200,7 +190,7 @@ namespace Emby.Server.Implementations.IO var paths = LibraryManager .RootFolder .Children - .Where(IsLibraryMonitorEnabaled) + .Where(IsLibraryMonitorEnabled) .OfType<Folder>() .SelectMany(f => f.PhysicalLocations) .Distinct(StringComparer.OrdinalIgnoreCase) @@ -223,7 +213,7 @@ namespace Emby.Server.Implementations.IO private void StartWatching(BaseItem item) { - if (IsLibraryMonitorEnabaled(item)) + if (IsLibraryMonitorEnabled(item)) { StartWatchingPath(item.Path); } @@ -287,7 +277,7 @@ namespace Emby.Server.Implementations.IO /// <param name="path">The path.</param> private void StartWatchingPath(string path) { - if (!_fileSystem.DirectoryExists(path)) + if (!Directory.Exists(path)) { // Seeing a crash in the mono runtime due to an exception being thrown on a different thread Logger.LogInformation("Skipping realtime monitor for {0} because the path does not exist", path); @@ -493,7 +483,7 @@ namespace Emby.Server.Implementations.IO } // Go up a level - var parent = _fileSystem.GetDirectoryName(i); + var parent = Path.GetDirectoryName(i); if (!string.IsNullOrEmpty(parent)) { if (_fileSystem.AreEqual(parent, path)) @@ -519,7 +509,7 @@ namespace Emby.Server.Implementations.IO private void CreateRefresher(string path) { - var parentPath = _fileSystem.GetDirectoryName(path); + var parentPath = Path.GetDirectoryName(path); lock (_activeRefreshers) { @@ -548,7 +538,7 @@ namespace Emby.Server.Implementations.IO } // They are siblings. Rebase the refresher to the parent folder. - if (string.Equals(parentPath, _fileSystem.GetDirectoryName(refresher.Path), StringComparison.Ordinal)) + if (string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal)) { refresher.ResetPath(parentPath, path); return; diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 3e7774abf..7c44878ec 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.IO _isEnvironmentCaseInsensitive = environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows; } - public string DefaultDirectory + public virtual string DefaultDirectory { get { @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.IO { try { - if (DirectoryExists(value)) + if (Directory.Exists(value)) { return value; } @@ -75,7 +75,7 @@ namespace Emby.Server.Implementations.IO } } - public void AddShortcutHandler(IShortcutHandler handler) + public virtual void AddShortcutHandler(IShortcutHandler handler) { _shortcutHandlers.Add(handler); } @@ -94,13 +94,6 @@ namespace Emby.Server.Implementations.IO } } - public char DirectorySeparatorChar => Path.DirectorySeparatorChar; - - public string GetFullPath(string path) - { - return Path.GetFullPath(path); - } - /// <summary> /// Determines whether the specified filename is shortcut. /// </summary> @@ -142,7 +135,7 @@ namespace Emby.Server.Implementations.IO return null; } - public string MakeAbsolutePath(string folderPath, string filePath) + public virtual string MakeAbsolutePath(string folderPath, string filePath) { if (string.IsNullOrWhiteSpace(filePath)) return filePath; @@ -195,7 +188,7 @@ namespace Emby.Server.Implementations.IO /// or /// target /// </exception> - public void CreateShortcut(string shortcutPath, string target) + public virtual void CreateShortcut(string shortcutPath, string target) { if (string.IsNullOrEmpty(shortcutPath)) { @@ -227,7 +220,7 @@ namespace Emby.Server.Implementations.IO /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and all other properties will reflect the properties of the directory.</remarks> - public FileSystemMetadata GetFileSystemInfo(string path) + public virtual FileSystemMetadata GetFileSystemInfo(string path) { // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists if (Path.HasExtension(path)) @@ -262,7 +255,7 @@ namespace Emby.Server.Implementations.IO /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's /// <see cref="FileSystemMetadata.IsDirectory"/> property and the <see cref="FileSystemMetadata.Exists"/> property will both be set to false.</para> /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> - public FileSystemMetadata GetFileInfo(string path) + public virtual FileSystemMetadata GetFileInfo(string path) { var fileInfo = new FileInfo(path); @@ -277,7 +270,7 @@ namespace Emby.Server.Implementations.IO /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata"/> object's /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and the <see cref="FileSystemMetadata.Exists"/> property will be set to false.</para> /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> - public FileSystemMetadata GetDirectoryInfo(string path) + public virtual FileSystemMetadata GetDirectoryInfo(string path) { var fileInfo = new DirectoryInfo(path); @@ -340,23 +333,18 @@ namespace Emby.Server.Implementations.IO } /// <summary> - /// The space char - /// </summary> - private const char SpaceChar = ' '; - - /// <summary> /// Takes a filename and removes invalid characters /// </summary> /// <param name="filename">The filename.</param> /// <returns>System.String.</returns> /// <exception cref="ArgumentNullException">filename</exception> - public string GetValidFilename(string filename) + public virtual string GetValidFilename(string filename) { var builder = new StringBuilder(filename); foreach (var c in _invalidFileNameChars) { - builder = builder.Replace(c, SpaceChar); + builder = builder.Replace(c, ' '); } return builder.ToString(); @@ -386,17 +374,17 @@ namespace Emby.Server.Implementations.IO /// </summary> /// <param name="path">The path.</param> /// <returns>DateTime.</returns> - public DateTime GetCreationTimeUtc(string path) + public virtual DateTime GetCreationTimeUtc(string path) { return GetCreationTimeUtc(GetFileSystemInfo(path)); } - public DateTime GetCreationTimeUtc(FileSystemMetadata info) + public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info) { return info.CreationTimeUtc; } - public DateTime GetLastWriteTimeUtc(FileSystemMetadata info) + public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info) { return info.LastWriteTimeUtc; } @@ -425,7 +413,7 @@ namespace Emby.Server.Implementations.IO /// </summary> /// <param name="path">The path.</param> /// <returns>DateTime.</returns> - public DateTime GetLastWriteTimeUtc(string path) + public virtual DateTime GetLastWriteTimeUtc(string path) { return GetLastWriteTimeUtc(GetFileSystemInfo(path)); } @@ -439,7 +427,7 @@ namespace Emby.Server.Implementations.IO /// <param name="share">The share.</param> /// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param> /// <returns>FileStream.</returns> - public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false) + public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false) { if (_supportsAsyncFileStreams && isAsync) { @@ -449,7 +437,7 @@ namespace Emby.Server.Implementations.IO return GetFileStream(path, mode, access, share, FileOpenOptions.None); } - public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions) + public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions) => new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 4096, GetFileOptions(fileOpenOptions)); private static FileOptions GetFileOptions(FileOpenOptions mode) @@ -511,7 +499,7 @@ namespace Emby.Server.Implementations.IO } } - public void SetHidden(string path, bool isHidden) + public virtual void SetHidden(string path, bool isHidden) { if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) { @@ -535,7 +523,7 @@ namespace Emby.Server.Implementations.IO } } - public void SetReadOnly(string path, bool isReadOnly) + public virtual void SetReadOnly(string path, bool isReadOnly) { if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) { @@ -559,7 +547,7 @@ namespace Emby.Server.Implementations.IO } } - public void SetAttributes(string path, bool isHidden, bool isReadOnly) + public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly) { if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) { @@ -611,7 +599,7 @@ namespace Emby.Server.Implementations.IO /// </summary> /// <param name="file1">The file1.</param> /// <param name="file2">The file2.</param> - public void SwapFiles(string file1, string file2) + public virtual void SwapFiles(string file1, string file2) { if (string.IsNullOrEmpty(file1)) { @@ -630,18 +618,13 @@ namespace Emby.Server.Implementations.IO SetHidden(file2, false); Directory.CreateDirectory(_tempPath); - CopyFile(file1, temp1, true); + File.Copy(file1, temp1, true); - CopyFile(file2, file1, true); - CopyFile(temp1, file2, true); + File.Copy(file2, file1, true); + File.Copy(temp1, file2, true); } - private static char GetDirectorySeparatorChar(string path) - { - return Path.DirectorySeparatorChar; - } - - public bool ContainsSubPath(string parentPath, string path) + public virtual bool ContainsSubPath(string parentPath, string path) { if (string.IsNullOrEmpty(parentPath)) { @@ -653,19 +636,19 @@ namespace Emby.Server.Implementations.IO throw new ArgumentNullException(nameof(path)); } - var separatorChar = GetDirectorySeparatorChar(parentPath); + var separatorChar = Path.DirectorySeparatorChar; return path.IndexOf(parentPath.TrimEnd(separatorChar) + separatorChar, StringComparison.OrdinalIgnoreCase) != -1; } - public bool IsRootPath(string path) + public virtual bool IsRootPath(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException(nameof(path)); } - var parent = GetDirectoryName(path); + var parent = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(parent)) { @@ -675,12 +658,7 @@ namespace Emby.Server.Implementations.IO return true; } - public string GetDirectoryName(string path) - { - return Path.GetDirectoryName(path); - } - - public string NormalizePath(string path) + public virtual string NormalizePath(string path) { if (string.IsNullOrEmpty(path)) { @@ -692,10 +670,10 @@ namespace Emby.Server.Implementations.IO return path; } - return path.TrimEnd(GetDirectorySeparatorChar(path)); + return path.TrimEnd(Path.DirectorySeparatorChar); } - public bool AreEqual(string path1, string path2) + public virtual bool AreEqual(string path1, string path2) { if (path1 == null && path2 == null) { @@ -710,7 +688,7 @@ namespace Emby.Server.Implementations.IO return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase); } - public string GetFileNameWithoutExtension(FileSystemMetadata info) + public virtual string GetFileNameWithoutExtension(FileSystemMetadata info) { if (info.IsDirectory) { @@ -720,12 +698,7 @@ namespace Emby.Server.Implementations.IO return Path.GetFileNameWithoutExtension(info.FullName); } - public string GetFileNameWithoutExtension(string path) - { - return Path.GetFileNameWithoutExtension(path); - } - - public bool IsPathFile(string path) + public virtual bool IsPathFile(string path) { // Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\ @@ -740,23 +713,13 @@ namespace Emby.Server.Implementations.IO //return Path.IsPathRooted(path); } - public void DeleteFile(string path) + public virtual void DeleteFile(string path) { SetAttributes(path, false, false); File.Delete(path); } - - public void DeleteDirectory(string path, bool recursive) - { - Directory.Delete(path, recursive); - } - - public void CreateDirectory(string path) - { - Directory.CreateDirectory(path); - } - - public List<FileSystemMetadata> GetDrives() + + public virtual List<FileSystemMetadata> GetDrives() { // Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemMetadata @@ -768,19 +731,19 @@ namespace Emby.Server.Implementations.IO }).ToList(); } - public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false) + public virtual IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", searchOption)); } - public IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false) + public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false) { return GetFiles(path, null, false, recursive); } - public IEnumerable<FileSystemMetadata> GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; @@ -809,7 +772,7 @@ namespace Emby.Server.Implementations.IO return ToMetadata(files); } - public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false) + public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false) { var directoryInfo = new DirectoryInfo(path); var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; @@ -827,89 +790,19 @@ namespace Emby.Server.Implementations.IO { return infos.Select(GetFileSystemMetadata); } - - public string[] ReadAllLines(string path) - { - return File.ReadAllLines(path); - } - - public void WriteAllLines(string path, IEnumerable<string> lines) - { - File.WriteAllLines(path, lines); - } - - public Stream OpenRead(string path) - { - return File.OpenRead(path); - } - - public void CopyFile(string source, string target, bool overwrite) - { - File.Copy(source, target, overwrite); - } - - public void MoveFile(string source, string target) - { - File.Move(source, target); - } - - public void MoveDirectory(string source, string target) - { - Directory.Move(source, target); - } - - public bool DirectoryExists(string path) - { - return Directory.Exists(path); - } - - public bool FileExists(string path) - { - return File.Exists(path); - } - - public string ReadAllText(string path) - { - return File.ReadAllText(path); - } - - public byte[] ReadAllBytes(string path) - { - return File.ReadAllBytes(path); - } - - public void WriteAllText(string path, string text, Encoding encoding) - { - File.WriteAllText(path, text, encoding); - } - - public void WriteAllText(string path, string text) - { - File.WriteAllText(path, text); - } - - public void WriteAllBytes(string path, byte[] bytes) - { - File.WriteAllBytes(path, bytes); - } - - public string ReadAllText(string path, Encoding encoding) - { - return File.ReadAllText(path, encoding); - } - - public IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false) + + public virtual IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return Directory.EnumerateDirectories(path, "*", searchOption); } - public IEnumerable<string> GetFilePaths(string path, bool recursive = false) + public virtual IEnumerable<string> GetFilePaths(string path, bool recursive = false) { return GetFilePaths(path, null, false, recursive); } - public IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; @@ -938,7 +831,7 @@ namespace Emby.Server.Implementations.IO return files; } - public IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false) + public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return Directory.EnumerateFileSystemEntries(path, "*", searchOption); @@ -948,7 +841,7 @@ namespace Emby.Server.Implementations.IO { if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX) { - RunProcess("chmod", "+x \"" + path + "\"", GetDirectoryName(path)); + RunProcess("chmod", "+x \"" + path + "\"", Path.GetDirectoryName(path)); } } diff --git a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs index a306f94b3..5e5e91bb3 100644 --- a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs +++ b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.IO if (string.Equals(Path.GetExtension(shortcutPath), ".mblink", StringComparison.OrdinalIgnoreCase)) { - var path = _fileSystem.ReadAllText(shortcutPath); + var path = File.ReadAllText(shortcutPath); return _fileSystem.NormalizePath(path); } @@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.IO throw new ArgumentNullException(nameof(targetPath)); } - _fileSystem.WriteAllText(shortcutPath, targetPath); + File.WriteAllText(shortcutPath, targetPath); } } } diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index b99b98157..9705d54c9 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.Images CancellationToken cancellationToken) { var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N")); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPathWithoutExtension)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension)); string outputPath = CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0); if (string.IsNullOrEmpty(outputPath)) @@ -165,7 +165,7 @@ namespace Emby.Server.Implementations.Images private string CreateCollage(BaseItem primaryItem, List<BaseItem> items, string outputPath, int width, int height) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); var options = new ImageCollageOptions { @@ -300,7 +300,7 @@ namespace Emby.Server.Implementations.Images var ext = Path.GetExtension(image); var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext); - FileSystem.CopyFile(image, outputPath, true); + File.Copy(image, outputPath, true); return outputPath; } diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index c0a126b84..80f746c7a 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -146,7 +147,7 @@ namespace Emby.Server.Implementations.Library if (parent != null) { // Don't resolve these into audio files - if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename)) + if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename)) { return true; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index ad070ed79..f96a211ec 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -375,7 +375,7 @@ namespace Emby.Server.Implementations.Library try { - _fileSystem.DeleteDirectory(metadataPath, true); + Directory.Delete(metadataPath, true); } catch (IOException) { @@ -395,38 +395,33 @@ namespace Emby.Server.Implementations.Library foreach (var fileSystemInfo in item.GetDeletePaths().ToList()) { - try + if (File.Exists(fileSystemInfo.FullName)) { - _logger.LogDebug("Deleting path {path}", fileSystemInfo.FullName); - if (fileSystemInfo.IsDirectory) + try { - _fileSystem.DeleteDirectory(fileSystemInfo.FullName, true); + _logger.LogDebug("Deleting path {path}", fileSystemInfo.FullName); + if (fileSystemInfo.IsDirectory) + { + Directory.Delete(fileSystemInfo.FullName, true); + } + else + { + File.Delete(fileSystemInfo.FullName); + } } - else + catch (IOException) { - _fileSystem.DeleteFile(fileSystemInfo.FullName); + if (isRequiredForDelete) + { + throw; + } } - } - catch (FileNotFoundException) - { - // may have already been deleted manually by user - } - catch (DirectoryNotFoundException) - { - // may have already been deleted manually by user - } - catch (IOException) - { - if (isRequiredForDelete) - { - throw; - } - } - catch (UnauthorizedAccessException) - { - if (isRequiredForDelete) + catch (UnauthorizedAccessException) { - throw; + if (isRequiredForDelete) + { + throw; + } } } @@ -725,7 +720,7 @@ namespace Emby.Server.Implementations.Library { var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath; - _fileSystem.CreateDirectory(rootFolderPath); + Directory.CreateDirectory(rootFolderPath); var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath))).DeepCopy<Folder, AggregateFolder>(); @@ -739,7 +734,7 @@ namespace Emby.Server.Implementations.Library // Add in the plug-in folders var path = Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "playlists"); - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); Folder folder = new PlaylistsFolder { @@ -790,7 +785,7 @@ namespace Emby.Server.Implementations.Library { var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - _fileSystem.CreateDirectory(userRootPath); + Directory.CreateDirectory(userRootPath); var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; @@ -1004,7 +999,7 @@ namespace Emby.Server.Implementations.Library public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) { // Ensure the location is available. - _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress); } @@ -1233,7 +1228,7 @@ namespace Emby.Server.Implementations.Library private string GetCollectionType(string path) { return _fileSystem.GetFilePaths(path, new[] { ".collection" }, true, false) - .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) + .Select(i => Path.GetFileNameWithoutExtension(i)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); } @@ -2151,7 +2146,7 @@ namespace Emby.Server.Implementations.Library if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase)) { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); item = new UserView { @@ -2196,7 +2191,7 @@ namespace Emby.Server.Implementations.Library if (item == null) { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); item = new UserView { @@ -2261,7 +2256,7 @@ namespace Emby.Server.Implementations.Library if (item == null) { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); item = new UserView { @@ -2329,7 +2324,7 @@ namespace Emby.Server.Implementations.Library if (item == null) { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); item = new UserView { @@ -2868,7 +2863,7 @@ namespace Emby.Server.Implementations.Library var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, name); - while (_fileSystem.DirectoryExists(virtualFolderPath)) + while (Directory.Exists(virtualFolderPath)) { name += "1"; virtualFolderPath = Path.Combine(rootFolderPath, name); @@ -2877,7 +2872,7 @@ namespace Emby.Server.Implementations.Library var mediaPathInfos = options.PathInfos; if (mediaPathInfos != null) { - var invalidpath = mediaPathInfos.FirstOrDefault(i => !_fileSystem.DirectoryExists(i.Path)); + var invalidpath = mediaPathInfos.FirstOrDefault(i => !Directory.Exists(i.Path)); if (invalidpath != null) { throw new ArgumentException("The specified path does not exist: " + invalidpath.Path + "."); @@ -2888,13 +2883,13 @@ namespace Emby.Server.Implementations.Library try { - _fileSystem.CreateDirectory(virtualFolderPath); + Directory.CreateDirectory(virtualFolderPath); if (!string.IsNullOrEmpty(collectionType)) { var path = Path.Combine(virtualFolderPath, collectionType + ".collection"); - _fileSystem.WriteAllBytes(path, Array.Empty<byte>()); + File.WriteAllBytes(path, Array.Empty<byte>()); } CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); @@ -2940,7 +2935,7 @@ namespace Emby.Server.Implementations.Library // // We can't validate protocol-based paths, so just allow them // if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) // { - // return _fileSystem.DirectoryExists(path); + // return Directory.Exists(path); // } //} @@ -2968,7 +2963,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(path)); } - if (!_fileSystem.DirectoryExists(path)) + if (!Directory.Exists(path)) { throw new FileNotFoundException("The path does not exist."); } @@ -2981,11 +2976,11 @@ namespace Emby.Server.Implementations.Library var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); + var shortcutFilename = Path.GetFileNameWithoutExtension(path); var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - while (_fileSystem.FileExists(lnk)) + while (File.Exists(lnk)) { shortcutFilename += "1"; lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); @@ -3078,7 +3073,7 @@ namespace Emby.Server.Implementations.Library var path = Path.Combine(rootFolderPath, name); - if (!_fileSystem.DirectoryExists(path)) + if (!Directory.Exists(path)) { throw new FileNotFoundException("The media folder does not exist"); } @@ -3087,7 +3082,7 @@ namespace Emby.Server.Implementations.Library try { - _fileSystem.DeleteDirectory(path, true); + Directory.Delete(path, true); } finally { @@ -3150,7 +3145,7 @@ namespace Emby.Server.Implementations.Library var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - if (!_fileSystem.DirectoryExists(virtualFolderPath)) + if (!Directory.Exists(virtualFolderPath)) { throw new FileNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName)); } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 1ed838893..b83fb9b39 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -670,7 +670,7 @@ namespace Emby.Server.Implementations.Library if (cacheFilePath != null) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath); //_logger.LogDebug("Saved media info to {0}", cacheFilePath); diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 78c1c6629..9de766767 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers var filename = Path.GetFileNameWithoutExtension(args.Path); // Make sure the image doesn't belong to a video file - var files = args.DirectoryService.GetFiles(_fileSystem.GetDirectoryName(args.Path)); + var files = args.DirectoryService.GetFiles(Path.GetDirectoryName(args.Path)); var libraryOptions = args.GetLibraryOptions(); foreach (var file in files) diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 6139659b7..05fce4542 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -904,7 +904,7 @@ namespace Emby.Server.Implementations.Library // Tuesday, 22 August 2006 06:30 AM text.AppendLine("The pin code will expire at " + localExpirationTime.ToString("f1", CultureInfo.CurrentCulture)); - _fileSystem.WriteAllText(path, text.ToString(), Encoding.UTF8); + File.WriteAllText(path, text.ToString(), Encoding.UTF8); var result = new PasswordPinCreationResult { @@ -1029,6 +1029,11 @@ namespace Emby.Server.Implementations.Library { var path = GetPolicyFilePath(user); + if (!File.Exists(path)) + { + return GetDefaultPolicy(user); + } + try { lock (_policySyncLock) @@ -1036,10 +1041,6 @@ namespace Emby.Server.Implementations.Library return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path); } } - catch (FileNotFoundException) - { - return GetDefaultPolicy(user); - } catch (IOException) { return GetDefaultPolicy(user); @@ -1079,7 +1080,7 @@ namespace Emby.Server.Implementations.Library var path = GetPolicyFilePath(user); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_policySyncLock) { @@ -1128,6 +1129,11 @@ namespace Emby.Server.Implementations.Library { var path = GetConfigurationFilePath(user); + if (!File.Exists(path)) + { + return new UserConfiguration(); + } + try { lock (_configSyncLock) @@ -1135,10 +1141,6 @@ namespace Emby.Server.Implementations.Library return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path); } } - catch (FileNotFoundException) - { - return new UserConfiguration(); - } catch (IOException) { return new UserConfiguration(); @@ -1174,7 +1176,7 @@ namespace Emby.Server.Implementations.Library config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json); } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_configSyncLock) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 7d7ef21e3..dd636e6cd 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; @@ -41,7 +42,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordFromDirectStreamProvider(IDirectStreamProvider directStreamProvider, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); + Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { @@ -77,7 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _logger.LogInformation("Opened recording stream from tuner provider"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); + Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 9e11494c9..6a2a46c9f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -60,7 +60,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IProviderManager _providerManager; private readonly IMediaEncoder _mediaEncoder; private readonly IProcessFactory _processFactory; - private readonly ISystemEvents _systemEvents; private readonly IAssemblyInfo _assemblyInfo; private IMediaSourceManager _mediaSourceManager; @@ -90,8 +89,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IProviderManager providerManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory, - IProcessFactory processFactory, - ISystemEvents systemEvents) + IProcessFactory processFactory) { Current = this; @@ -105,7 +103,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _providerManager = providerManager; _mediaEncoder = mediaEncoder; _processFactory = processFactory; - _systemEvents = systemEvents; _liveTvManager = (LiveTvManager)liveTvManager; _jsonSerializer = jsonSerializer; _assemblyInfo = assemblyInfo; @@ -131,15 +128,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _timerProvider.RestartTimers(); - _systemEvents.Resume += _systemEvents_Resume; await CreateRecordingFolders().ConfigureAwait(false); } - private void _systemEvents_Resume(object sender, EventArgs e) - { - _timerProvider.RestartTimers(); - } - private async void OnRecordingFoldersChanged() { await CreateRecordingFolders().ConfigureAwait(false); @@ -1436,7 +1427,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV timer.RetryCount++; _timerProvider.AddOrUpdate(timer); } - else if (_fileSystem.FileExists(recordPath)) + else if (File.Exists(recordPath)) { timer.RecordingPath = recordPath; timer.Status = RecordingStatus.Completed; @@ -1498,7 +1489,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _logger.LogInformation("Triggering refresh on {path}", path); - var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path)); + var item = GetAffectedBaseItem(Path.GetDirectoryName(path)); if (item != null) { @@ -1509,8 +1500,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV RefreshPaths = new string[] { path, - _fileSystem.GetDirectoryName(path), - _fileSystem.GetDirectoryName(_fileSystem.GetDirectoryName(path)) + Path.GetDirectoryName(path), + Path.GetDirectoryName(Path.GetDirectoryName(path)) } }, RefreshPriority.High); @@ -1521,13 +1512,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { BaseItem item = null; - var parentPath = _fileSystem.GetDirectoryName(path); + var parentPath = Path.GetDirectoryName(path); while (item == null && !string.IsNullOrEmpty(path)) { item = _libraryManager.FindByPath(path, null); - path = _fileSystem.GetDirectoryName(path); + path = Path.GetDirectoryName(path); } if (item != null) @@ -1582,7 +1573,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV .Where(i => i.Status == RecordingStatus.Completed && !string.IsNullOrWhiteSpace(i.RecordingPath)) .Where(i => string.Equals(i.SeriesTimerId, seriesTimerId, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(i => i.EndDate) - .Where(i => _fileSystem.FileExists(i.RecordingPath)) + .Where(i => File.Exists(i.RecordingPath)) .Skip(seriesTimer.KeepUpTo - 1) .ToList(); @@ -1604,7 +1595,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV DtoOptions = new DtoOptions(true) })) - .Where(i => i.IsFileProtocol && _fileSystem.FileExists(i.Path)) + .Where(i => i.IsFileProtocol && File.Exists(i.Path)) .Skip(seriesTimer.KeepUpTo - 1) .ToList(); @@ -1685,7 +1676,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV while (FileExists(path, timerId)) { - var parent = _fileSystem.GetDirectoryName(originalPath); + var parent = Path.GetDirectoryName(originalPath); var name = Path.GetFileNameWithoutExtension(originalPath); name += " - " + index.ToString(CultureInfo.InvariantCulture); @@ -1698,7 +1689,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private bool FileExists(string path, string timerId) { - if (_fileSystem.FileExists(path)) + if (File.Exists(path)) { return true; } @@ -1831,12 +1822,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension); + var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension); // preserve original image extension imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path)); - _fileSystem.CopyFile(image.Path, imageSavePath, true); + File.Copy(image.Path, imageSavePath, true); } private async Task SaveRecordingImages(string recordingPath, LiveTvProgram program) @@ -1970,7 +1961,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var nfoPath = Path.Combine(seriesPath, "tvshow.nfo"); - if (_fileSystem.FileExists(nfoPath)) + if (File.Exists(nfoPath)) { return; } @@ -2032,7 +2023,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var nfoPath = Path.ChangeExtension(recordingPath, ".nfo"); - if (_fileSystem.FileExists(nfoPath)) + if (File.Exists(nfoPath)) { return; } @@ -2697,7 +2688,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var defaultFolder = RecordingPath; var defaultName = "Recordings"; - if (_fileSystem.DirectoryExists(defaultFolder)) + if (Directory.Exists(defaultFolder)) { list.Add(new VirtualFolderInfo { @@ -2707,7 +2698,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } var customPath = GetConfiguration().MovieRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && _fileSystem.DirectoryExists(customPath)) + if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) { list.Add(new VirtualFolderInfo { @@ -2718,7 +2709,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } customPath = GetConfiguration().SeriesRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && _fileSystem.DirectoryExists(customPath)) + if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) { list.Add(new VirtualFolderInfo { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index c11a85027..eed239514 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { _targetPath = targetFile; - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); + Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); var process = _processFactory.Create(new ProcessOptions { @@ -105,7 +105,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath)); + Directory.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. _logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 1b8287ed1..6b02eaea8 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } var file = _dataPath + ".json"; - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file)); + Directory.CreateDirectory(Path.GetDirectoryName(file)); lock (_fileDataLock) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index e7a3d748d..f152ac465 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -61,7 +61,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); - if (_fileSystem.FileExists(cacheFile)) + if (File.Exists(cacheFile)) { return UnzipIfNeeded(path, cacheFile); } @@ -83,9 +83,9 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings }).ConfigureAwait(false); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile)); + Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); - _fileSystem.CopyFile(tempFile, cacheFile, true); + File.Copy(tempFile, cacheFile, true); return UnzipIfNeeded(path, cacheFile); } @@ -122,10 +122,10 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings private string ExtractFirstFileFromGz(string file) { - using (var stream = _fileSystem.OpenRead(file)) + using (var stream = File.OpenRead(file)) { string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); + Directory.CreateDirectory(tempFolder); _zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml"); @@ -135,10 +135,10 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings private string ExtractGz(string file) { - using (var stream = _fileSystem.OpenRead(file)) + using (var stream = File.OpenRead(file)) { string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); + Directory.CreateDirectory(tempFolder); _zipClient.ExtractAllFromGz(stream, tempFolder, true); @@ -255,7 +255,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings) { // Assume all urls are valid. check files for existence - if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) && !_fileSystem.FileExists(info.Path)) + if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) && !File.Exists(info.Path)) { throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index ee86f66e6..6d1eff187 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(channelCacheFile)); + Directory.CreateDirectory(Path.GetDirectoryName(channelCacheFile)); JsonSerializer.SerializeToFile(channels, channelCacheFile); } catch (IOException) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 2542ddd2a..8774371d5 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var uri = new Uri(mediaSource.Path); var localPort = _networkManager.GetRandomUnusedUdpPort(); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index a54a53b25..9a01c42d3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts UserAgent = _appHost.ApplicationUserAgent }); } - return Task.FromResult(_fileSystem.OpenRead(url)); + return Task.FromResult((Stream)File.OpenRead(url)); } const string ExtInfPrefix = "#EXTINF:"; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index b39a9f679..716417ccb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; @@ -35,7 +36,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var url = mediaSource.Path; - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); var typeName = GetType().Name; Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url); diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index af05cd7d7..7af8cf18c 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.Localization var localizationPath = LocalizationPath; - _fileSystem.CreateDirectory(localizationPath); + Directory.CreateDirectory(localizationPath); var existingFiles = GetRatingsFiles(localizationPath) .Select(Path.GetFileName) @@ -316,7 +316,7 @@ namespace Emby.Server.Implementations.Localization /// <returns>Dictionary{System.StringParentalRating}.</returns> private void LoadRatings(string file) { - var dict = _fileSystem.ReadAllLines(file).Select(i => + var dict = File.ReadAllLines(file).Select(i => { if (!string.IsNullOrWhiteSpace(i)) { @@ -337,7 +337,7 @@ namespace Emby.Server.Implementations.Localization .Where(i => i != null) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - var countryCode = _fileSystem.GetFileNameWithoutExtension(file) + var countryCode = Path.GetFileNameWithoutExtension(file) .Split('-') .Last(); @@ -502,58 +502,55 @@ namespace Emby.Server.Implementations.Localization return culture + ".json"; } - public LocalizatonOption[] GetLocalizationOptions() - { - return new LocalizatonOption[] + public LocalizationOption[] GetLocalizationOptions() + => new LocalizationOption[] { - new LocalizatonOption{ Name="Arabic", Value="ar"}, - new LocalizatonOption{ Name="Belarusian (Belarus)", Value="be-BY"}, - new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"}, - new LocalizatonOption{ Name="Catalan", Value="ca"}, - new LocalizatonOption{ Name="Chinese Simplified", Value="zh-CN"}, - new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, - new LocalizatonOption{ Name="Chinese Traditional (Hong Kong)", Value="zh-HK"}, - new LocalizatonOption{ Name="Croatian", Value="hr"}, - new LocalizatonOption{ Name="Czech", Value="cs"}, - new LocalizatonOption{ Name="Danish", Value="da"}, - new LocalizatonOption{ Name="Dutch", Value="nl"}, - new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, - new LocalizatonOption{ Name="English (United States)", Value="en-US"}, - new LocalizatonOption{ Name="Finnish", Value="fi"}, - new LocalizatonOption{ Name="French", Value="fr"}, - new LocalizatonOption{ Name="French (Canada)", Value="fr-CA"}, - new LocalizatonOption{ Name="German", Value="de"}, - new LocalizatonOption{ Name="Greek", Value="el"}, - new LocalizatonOption{ Name="Hebrew", Value="he"}, - new LocalizatonOption{ Name="Hindi (India)", Value="hi-IN"}, - new LocalizatonOption{ Name="Hungarian", Value="hu"}, - new LocalizatonOption{ Name="Indonesian", Value="id"}, - new LocalizatonOption{ Name="Italian", Value="it"}, - new LocalizatonOption{ Name="Japanese", Value="ja"}, - new LocalizatonOption{ Name="Kazakh", Value="kk"}, - new LocalizatonOption{ Name="Korean", Value="ko"}, - new LocalizatonOption{ Name="Lithuanian", Value="lt-LT"}, - new LocalizatonOption{ Name="Malay", Value="ms"}, - new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"}, - new LocalizatonOption{ Name="Persian", Value="fa"}, - new LocalizatonOption{ Name="Polish", Value="pl"}, - new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, - new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, - new LocalizatonOption{ Name="Romanian", Value="ro"}, - new LocalizatonOption{ Name="Russian", Value="ru"}, - new LocalizatonOption{ Name="Slovak", Value="sk"}, - new LocalizatonOption{ Name="Slovenian (Slovenia)", Value="sl-SI"}, - new LocalizatonOption{ Name="Spanish", Value="es"}, - new LocalizatonOption{ Name="Spanish (Latin America)", Value="es-419"}, - new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}, - new LocalizatonOption{ Name="Swedish", Value="sv"}, - new LocalizatonOption{ Name="Swiss German", Value="gsw"}, - new LocalizatonOption{ Name="Turkish", Value="tr"}, - new LocalizatonOption{ Name="Ukrainian", Value="uk"}, - new LocalizatonOption{ Name="Vietnamese", Value="vi"} - + new LocalizationOption("Arabic", "ar"), + new LocalizationOption("Belarusian (Belarus)", "be-BY"), + new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"), + new LocalizationOption("Catalan", "ca"), + new LocalizationOption("Chinese Simplified", "zh-CN"), + new LocalizationOption("Chinese Traditional", "zh-TW"), + new LocalizationOption("Chinese Traditional (Hong Kong)", "zh-HK"), + new LocalizationOption("Croatian", "hr"), + new LocalizationOption("Czech", "cs"), + new LocalizationOption("Danish", "da"), + new LocalizationOption("Dutch", "nl"), + new LocalizationOption("English (United Kingdom)", "en-GB"), + new LocalizationOption("English (United States)", "en-US"), + new LocalizationOption("Finnish", "fi"), + new LocalizationOption("French", "fr"), + new LocalizationOption("French (Canada)", "fr-CA"), + new LocalizationOption("German", "de"), + new LocalizationOption("Greek", "el"), + new LocalizationOption("Hebrew", "he"), + new LocalizationOption("Hindi (India)", "hi-IN"), + new LocalizationOption("Hungarian", "hu"), + new LocalizationOption("Indonesian", "id"), + new LocalizationOption("Italian", "it"), + new LocalizationOption("Japanese", "ja"), + new LocalizationOption("Kazakh", "kk"), + new LocalizationOption("Korean", "ko"), + new LocalizationOption("Lithuanian", "lt-LT"), + new LocalizationOption("Malay", "ms"), + new LocalizationOption("Norwegian Bokmål", "nb"), + new LocalizationOption("Persian", "fa"), + new LocalizationOption("Polish", "pl"), + new LocalizationOption("Portuguese (Brazil)", "pt-BR"), + new LocalizationOption("Portuguese (Portugal)", "pt-PT"), + new LocalizationOption("Romanian", "ro"), + new LocalizationOption("Russian", "ru"), + new LocalizationOption("Slovak", "sk"), + new LocalizationOption("Slovenian (Slovenia)", "sl-SI"), + new LocalizationOption("Spanish", "es"), + new LocalizationOption("Spanish (Latin America)", "es-419"), + new LocalizationOption("Spanish (Mexico)", "es-MX"), + new LocalizationOption("Swedish", "sv"), + new LocalizationOption("Swiss German", "gsw"), + new LocalizationOption("Turkish", "tr"), + new LocalizationOption("Ukrainian", "uk"), + new LocalizationOption("Vietnamese", "vi") }; - } } public interface ITextLocalizer diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 0575ff553..e68046f6d 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -141,12 +141,12 @@ namespace Emby.Server.Implementations.MediaEncoder var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, Array.Empty<string>()); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); var container = video.Container; var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); - _fileSystem.CopyFile(tempFile, path, true); + File.Copy(tempFile, path, true); try { diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 17f445708..29836e0bf 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.Playlists try { - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); var playlist = new Playlist { @@ -164,7 +164,7 @@ namespace Emby.Server.Implementations.Playlists private string GetTargetPath(string path) { - while (_fileSystem.DirectoryExists(path)) + while (Directory.Exists(path)) { path += "1"; } @@ -340,7 +340,8 @@ namespace Emby.Server.Implementations.Playlists playlist.PlaylistEntries.Add(entry); } - _fileSystem.WriteAllText(playlistPath, new WplContent().ToText(playlist)); + string text = new WplContent().ToText(playlist); + File.WriteAllText(playlistPath, text); } if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase)) { @@ -373,7 +374,8 @@ namespace Emby.Server.Implementations.Playlists playlist.PlaylistEntries.Add(entry); } - _fileSystem.WriteAllText(playlistPath, new ZplContent().ToText(playlist)); + string text = new ZplContent().ToText(playlist); + File.WriteAllText(playlistPath, text); } if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase)) { @@ -401,7 +403,8 @@ namespace Emby.Server.Implementations.Playlists playlist.PlaylistEntries.Add(entry); } - _fileSystem.WriteAllText(playlistPath, new M3uContent().ToText(playlist)); + string text = new M3uContent().ToText(playlist); + File.WriteAllText(playlistPath, text); } if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase)) { @@ -429,7 +432,8 @@ namespace Emby.Server.Implementations.Playlists playlist.PlaylistEntries.Add(entry); } - _fileSystem.WriteAllText(playlistPath, new M3u8Content().ToText(playlist)); + string text = new M3u8Content().ToText(playlist); + File.WriteAllText(playlistPath, text); } if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase)) { @@ -449,13 +453,14 @@ namespace Emby.Server.Implementations.Playlists playlist.PlaylistEntries.Add(entry); } - _fileSystem.WriteAllText(playlistPath, new PlsContent().ToText(playlist)); + string text = new PlsContent().ToText(playlist); + File.WriteAllText(playlistPath, text); } } private string NormalizeItemPath(string playlistPath, string itemPath) { - return MakeRelativePath(_fileSystem.GetDirectoryName(playlistPath), itemPath); + return MakeRelativePath(Path.GetDirectoryName(playlistPath), itemPath); } private static string MakeRelativePath(string folderPath, string fileAbsolutePath) diff --git a/Emby.Server.Implementations/ResourceFileManager.cs b/Emby.Server.Implementations/ResourceFileManager.cs index 6acc7e1d1..890d848f4 100644 --- a/Emby.Server.Implementations/ResourceFileManager.cs +++ b/Emby.Server.Implementations/ResourceFileManager.cs @@ -37,16 +37,16 @@ namespace Emby.Server.Implementations public string ReadAllText(string basePath, string virtualPath) { - return _fileSystem.ReadAllText(GetResourcePath(basePath, virtualPath)); + return File.ReadAllText(GetResourcePath(basePath, virtualPath)); } private string GetResourcePath(string basePath, string virtualPath) { - var fullPath = Path.Combine(basePath, virtualPath.Replace('/', _fileSystem.DirectorySeparatorChar)); + var fullPath = Path.Combine(basePath, virtualPath.Replace('/', Path.DirectorySeparatorChar)); try { - fullPath = _fileSystem.GetFullPath(fullPath); + fullPath = Path.GetFullPath(fullPath); } catch (Exception ex) { diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index 0ae7ae96c..5373b4392 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -101,17 +101,20 @@ namespace Emby.Server.Implementations.ScheduledTasks List<string> previouslyFailedImages; - try + if (File.Exists(failHistoryPath)) { - previouslyFailedImages = _fileSystem.ReadAllText(failHistoryPath) - .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) - .ToList(); - } - catch (FileNotFoundException) - { - previouslyFailedImages = new List<string>(); + try + { + previouslyFailedImages = File.ReadAllText(failHistoryPath) + .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) + .ToList(); + } + catch (IOException) + { + previouslyFailedImages = new List<string>(); + } } - catch (IOException) + else { previouslyFailedImages = new List<string>(); } @@ -136,11 +139,12 @@ namespace Emby.Server.Implementations.ScheduledTasks { previouslyFailedImages.Add(key); - var parentPath = _fileSystem.GetDirectoryName(failHistoryPath); + var parentPath = Path.GetDirectoryName(failHistoryPath); - _fileSystem.CreateDirectory(parentPath); + Directory.CreateDirectory(parentPath); - _fileSystem.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray())); + string text = string.Join("|", previouslyFailedImages); + File.WriteAllText(failHistoryPath, text); } numComplete++; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 44f6e2d7b..2b648b04b 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -53,7 +53,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <value>The task manager.</value> private ITaskManager TaskManager { get; set; } private readonly IFileSystem _fileSystem; - private readonly ISystemEvents _systemEvents; /// <summary> /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class. @@ -74,7 +73,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// or /// logger /// </exception> - public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents) + public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem) { if (scheduledTask == null) { @@ -103,7 +102,6 @@ namespace Emby.Server.Implementations.ScheduledTasks JsonSerializer = jsonSerializer; Logger = logger; _fileSystem = fileSystem; - _systemEvents = systemEvents; InitTriggerEvents(); } @@ -131,21 +129,16 @@ namespace Emby.Server.Implementations.ScheduledTasks { if (_lastExecutionResult == null && !_readFromFile) { - try + if (File.Exists(path)) { - _lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path); - } - catch (DirectoryNotFoundException) - { - // File doesn't exist. No biggie - } - catch (FileNotFoundException) - { - // File doesn't exist. No biggie - } - catch (Exception ex) - { - Logger.LogError(ex, "Error deserializing {path}", path); + try + { + _lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error deserializing {File}", path); + } } _readFromFile = true; } @@ -158,7 +151,7 @@ namespace Emby.Server.Implementations.ScheduledTasks _lastExecutionResult = value; var path = GetHistoryFilePath(); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); lock (_lastExecutionResultSyncLock) { @@ -534,28 +527,15 @@ namespace Emby.Server.Implementations.ScheduledTasks private TaskTriggerInfo[] LoadTriggerSettings() { - try - { - var list = JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath()); - - if (list != null) - { - return list.ToArray(); - } - } - catch (FileNotFoundException) - { - // File doesn't exist. No biggie. Return defaults. - } - catch (DirectoryNotFoundException) + string path = GetConfigurationFilePath(); + TaskTriggerInfo[] list = null; + if (File.Exists(path)) { - // File doesn't exist. No biggie. Return defaults. + list = JsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path); } - catch - { - } - return GetDefaultTriggers(); + // Return defaults if file doesn't exist. + return list ?? GetDefaultTriggers(); } private TaskTriggerInfo[] GetDefaultTriggers() @@ -585,7 +565,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { var path = GetConfigurationFilePath(); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); JsonSerializer.SerializeToFile(triggers, path); } @@ -762,20 +742,6 @@ namespace Emby.Server.Implementations.ScheduledTasks }; } - if (info.Type.Equals(typeof(SystemEventTrigger).Name, StringComparison.OrdinalIgnoreCase)) - { - if (!info.SystemEvent.HasValue) - { - throw new ArgumentException("Info did not contain a SystemEvent.", nameof(info)); - } - - return new SystemEventTrigger(_systemEvents) - { - SystemEvent = info.SystemEvent.Value, - TaskOptions = options - }; - } - if (info.Type.Equals(typeof(StartupTrigger).Name, StringComparison.OrdinalIgnoreCase)) { return new StartupTrigger(); diff --git a/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs deleted file mode 100644 index 7a88fc2b0..000000000 --- a/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Threading.Tasks; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Tasks; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class SystemEventTrigger - /// </summary> - public class SystemEventTrigger : ITaskTrigger - { - /// <summary> - /// Gets or sets the system event. - /// </summary> - /// <value>The system event.</value> - public SystemEvent SystemEvent { get; set; } - - /// <summary> - /// Gets or sets the options of this task. - /// </summary> - public TaskOptions TaskOptions { get; set; } - - private readonly ISystemEvents _systemEvents; - - public SystemEventTrigger(ISystemEvents systemEvents) - { - _systemEvents = systemEvents; - } - - /// <summary> - /// Stars waiting for the trigger action - /// </summary> - /// <param name="lastResult">The last result.</param> - /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup) - { - switch (SystemEvent) - { - case SystemEvent.WakeFromSleep: - _systemEvents.Resume += _systemEvents_Resume; - break; - } - } - - private async void _systemEvents_Resume(object sender, EventArgs e) - { - if (SystemEvent == SystemEvent.WakeFromSleep) - { - // This value is a bit arbitrary, but add a delay to help ensure network connections have been restored before running the task - await Task.Delay(10000).ConfigureAwait(false); - - OnTriggered(); - } - } - - /// <summary> - /// Stops waiting for the trigger action - /// </summary> - public void Stop() - { - _systemEvents.Resume -= _systemEvents_Resume; - } - - /// <summary> - /// Occurs when [triggered]. - /// </summary> - public event EventHandler<EventArgs> Triggered; - - /// <summary> - /// Called when [triggered]. - /// </summary> - private void OnTriggered() - { - if (Triggered != null) - { - Triggered(this, EventArgs.Empty); - } - } - } -} diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 02a082d3f..b8479fd26 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <value>The application paths.</value> private IApplicationPaths ApplicationPaths { get; set; } - private readonly ISystemEvents _systemEvents; - /// <summary> /// Gets the logger. /// </summary> @@ -66,54 +64,16 @@ namespace Emby.Server.Implementations.ScheduledTasks IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, - IFileSystem fileSystem, - ISystemEvents systemEvents) + IFileSystem fileSystem) { ApplicationPaths = applicationPaths; JsonSerializer = jsonSerializer; Logger = loggerFactory.CreateLogger(nameof(TaskManager)); _fileSystem = fileSystem; - _systemEvents = systemEvents; ScheduledTasks = new IScheduledTaskWorker[] { }; } - private void BindToSystemEvent() - { - _systemEvents.Resume += _systemEvents_Resume; - } - - private void _systemEvents_Resume(object sender, EventArgs e) - { - foreach (var task in ScheduledTasks) - { - task.ReloadTriggerEvents(); - } - } - - public void RunTaskOnNextStartup(string key) - { - var path = Path.Combine(ApplicationPaths.CachePath, "startuptasks.txt"); - - List<string> lines; - - try - { - lines = _fileSystem.ReadAllLines(path).ToList(); - } - catch - { - lines = new List<string>(); - } - - if (!lines.Contains(key, StringComparer.OrdinalIgnoreCase)) - { - lines.Add(key); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); - _fileSystem.WriteAllLines(path, lines); - } - } - private void RunStartupTasks() { var path = Path.Combine(ApplicationPaths.CachePath, "startuptasks.txt"); @@ -126,7 +86,7 @@ namespace Emby.Server.Implementations.ScheduledTasks try { - lines = _fileSystem.ReadAllLines(path).Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + lines = File.ReadAllLines(path).Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); foreach (var key in lines) { @@ -290,12 +250,10 @@ namespace Emby.Server.Implementations.ScheduledTasks var myTasks = ScheduledTasks.ToList(); var list = tasks.ToList(); - myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem, _systemEvents))); + myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem))); ScheduledTasks = myTasks.ToArray(); - BindToSystemEvent(); - RunStartupTasks(); } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 2590f455c..52077b242 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks { try { - _fileSystem.DeleteDirectory(directory, false); + Directory.Delete(directory, false); } catch (UnauthorizedAccessException ex) { diff --git a/Emby.Server.Implementations/Serialization/XmlSerializer.cs b/Emby.Server.Implementations/Serialization/XmlSerializer.cs index f7428eff7..6400ec16e 100644 --- a/Emby.Server.Implementations/Serialization/XmlSerializer.cs +++ b/Emby.Server.Implementations/Serialization/XmlSerializer.cs @@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Serialization public object DeserializeFromFile(Type type, string file) { _logger.LogDebug("Deserializing file {0}", file); - using (var stream = _fileSystem.OpenRead(file)) + using (var stream = File.OpenRead(file)) { return DeserializeFromStream(type, stream); } diff --git a/Emby.Server.Implementations/SystemEvents.cs b/Emby.Server.Implementations/SystemEvents.cs deleted file mode 100644 index e4c54c3c5..000000000 --- a/Emby.Server.Implementations/SystemEvents.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using MediaBrowser.Model.System; - -namespace Emby.Server.Implementations -{ - public class SystemEvents : ISystemEvents - { - public event EventHandler Resume; - public event EventHandler Suspend; - public event EventHandler SessionLogoff; - public event EventHandler SystemShutdown; - } -} diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 44377a897..552155635 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -555,7 +555,7 @@ namespace Emby.Server.Implementations.Updates var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum); if (!packageChecksum.Equals(Guid.Empty)) // support for legacy uploads for now { - using (var stream = _fileSystem.OpenRead(tempFile)) + using (var stream = File.OpenRead(tempFile)) { var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", string.Empty)); if (check != packageChecksum) @@ -570,12 +570,12 @@ namespace Emby.Server.Implementations.Updates // Success - move it to the real target try { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target)); - _fileSystem.CopyFile(tempFile, target, true); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(tempFile, target, true); //If it is an archive - write out a version file so we know what it is if (isArchive) { - _fileSystem.WriteAllText(target + ".ver", package.versionStr); + File.WriteAllText(target + ".ver", package.versionStr); } } catch (IOException ex) @@ -611,7 +611,7 @@ namespace Emby.Server.Implementations.Updates _logger.LogInformation("Deleting plugin file {0}", path); // Make this case-insensitive to account for possible incorrect assembly naming - var file = _fileSystem.GetFilePaths(_fileSystem.GetDirectoryName(path)) + var file = _fileSystem.GetFilePaths(Path.GetDirectoryName(path)) .FirstOrDefault(i => string.Equals(i, path, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(file)) diff --git a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs index 52e58ed8d..52ec7a135 100644 --- a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs +++ b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs @@ -1005,7 +1005,7 @@ namespace Emby.XmlTv.Classes } } - public static Regex _regDateWithOffset = new Regex(@"^(?<dateDigits>[0-9]{4,14})(\s(?<dateOffset>[+-]*[0-9]{1,4}))?$"); + public const string _regDateWithOffset = @"^(?<dateDigits>[0-9]{4,14})(\s(?<dateOffset>[+-]*[0-9]{1,4}))?$"; public DateTimeOffset? ParseDate(string dateValue) { @@ -1018,50 +1018,47 @@ namespace Emby.XmlTv.Classes '200007281733 BST', '200209', '19880523083000 +0300'. (BST == +0100.) */ - DateTimeOffset? result = null; - - if (!string.IsNullOrEmpty(dateValue)) + if (string.IsNullOrEmpty(dateValue)) { - var completeDate = "20000101000000"; - var dateComponent = string.Empty; - var dateOffset = "+00:00"; + return null; + } - var match = _regDateWithOffset.Match(dateValue); - if (match.Success) + var completeDate = "20000101000000"; + var dateComponent = string.Empty; + var dateOffset = "+00:00"; + var match = Regex.Match(dateValue, _regDateWithOffset); + if (match.Success) + { + dateComponent = match.Groups["dateDigits"].Value; + if (!string.IsNullOrEmpty(match.Groups["dateOffset"].Value)) { - dateComponent = match.Groups["dateDigits"].Value; - if (!string.IsNullOrEmpty(match.Groups["dateOffset"].Value)) + dateOffset = match.Groups["dateOffset"].Value; // Add in the colon to ease parsing later + if (dateOffset.Length == 5) { - dateOffset = match.Groups["dateOffset"].Value; // Add in the colon to ease parsing later - if (dateOffset.Length == 5) - { - dateOffset = dateOffset.Insert(3, ":"); // Add in the colon to ease parsing later - } - else - { - dateOffset = "+00:00"; - } + dateOffset = dateOffset.Insert(3, ":"); // Add in the colon to ease parsing later + } + else + { + dateOffset = "+00:00"; } } + } - // Pad out the date component part to 14 characaters so 2016061509 becomes 20160615090000 - if (dateComponent.Length < 14) - { - dateComponent = dateComponent + completeDate.Substring(dateComponent.Length, completeDate.Length - dateComponent.Length); - } + // Pad out the date component part to 14 characaters so 2016061509 becomes 20160615090000 + if (dateComponent.Length < 14) + { + dateComponent = dateComponent + completeDate.Substring(dateComponent.Length, completeDate.Length - dateComponent.Length); + } - var standardDate = string.Format("{0} {1}", dateComponent, dateOffset); - if (DateTimeOffset.TryParseExact(standardDate, "yyyyMMddHHmmss zzz", CultureInfo.CurrentCulture, DateTimeStyles.None, out var parsedDateTime)) - { - return parsedDateTime.ToUniversalTime(); - } - else - { - //Logger.LogWarning("Unable to parse the date {0} from standardised form {1}", dateValue, standardDate); - } + var standardDate = string.Format("{0} {1}", dateComponent, dateOffset); + if (DateTimeOffset.TryParseExact(standardDate, "yyyyMMddHHmmss zzz", CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTimeOffset parsedDateTime)) + { + return parsedDateTime.ToUniversalTime(); } - return result; + // Logger.LogWarning("Unable to parse the date {0} from standardised form {1}", dateValue, standardDate); + + return null; } public string StandardiseDate(string value) @@ -1070,7 +1067,7 @@ namespace Emby.XmlTv.Classes var dateComponent = string.Empty; var dateOffset = "+0000"; - var match = _regDateWithOffset.Match(value); + var match = Regex.Match(value, _regDateWithOffset); if (match.Success) { dateComponent = match.Groups["dateDigits"].Value; diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj new file mode 100644 index 000000000..f023bc55d --- /dev/null +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -0,0 +1,24 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <GenerateAssemblyInfo>false</GenerateAssemblyInfo> + </PropertyGroup> + + <ItemGroup> + <Compile Include="..\SharedVersion.cs" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="SkiaSharp" Version="1.68.0" /> + <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.0" /> + <PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> + <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> + <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> + </ItemGroup> + +</Project> diff --git a/Emby.Drawing/PercentPlayedDrawer.cs b/Jellyfin.Drawing.Skia/PercentPlayedDrawer.cs index 52b4329e1..0d5a1d3c0 100644 --- a/Emby.Drawing/PercentPlayedDrawer.cs +++ b/Jellyfin.Drawing.Skia/PercentPlayedDrawer.cs @@ -2,13 +2,13 @@ using System; using MediaBrowser.Model.Drawing; using SkiaSharp; -namespace Emby.Drawing +namespace Jellyfin.Drawing.Skia { public static class PercentPlayedDrawer { private const int IndicatorHeight = 8; - public static void Process(SKCanvas canvas, ImageSize imageSize, double percent) + public static void Process(SKCanvas canvas, ImageDimensions imageSize, double percent) { using (var paint = new SKPaint()) { @@ -24,7 +24,7 @@ namespace Emby.Drawing foregroundWidth /= 100; paint.Color = SKColor.Parse("#FF52B54B"); - canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), (float)endY), paint); + canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(foregroundWidth), (float)endY), paint); } } } diff --git a/Emby.Drawing/PlayedIndicatorDrawer.cs b/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs index a82398fa5..62497da27 100644 --- a/Emby.Drawing/PlayedIndicatorDrawer.cs +++ b/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs @@ -1,13 +1,13 @@ using MediaBrowser.Model.Drawing; using SkiaSharp; -namespace Emby.Drawing +namespace Jellyfin.Drawing.Skia { public static class PlayedIndicatorDrawer { private const int OffsetFromTopRightCorner = 38; - public static void DrawPlayedIndicator(SKCanvas canvas, ImageSize imageSize) + public static void DrawPlayedIndicator(SKCanvas canvas, ImageDimensions imageSize) { var x = imageSize.Width - OffsetFromTopRightCorner; diff --git a/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ea1c457f6 --- /dev/null +++ b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs @@ -0,0 +1,21 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Jellyfin.Drawing.Skia")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Jellyfin Project")] +[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] diff --git a/Emby.Drawing/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 9883b3cca..f1b886ec6 100644 --- a/Emby.Drawing/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -12,7 +12,7 @@ using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; using SkiaSharp; -namespace Emby.Drawing +namespace Jellyfin.Drawing.Skia { public class SkiaEncoder : IImageEncoder { @@ -72,16 +72,11 @@ namespace Emby.Drawing _logger.LogInformation("SkiaSharp version: " + GetVersion()); } - public static string GetVersion() - { - return typeof(SKBitmap).GetTypeInfo().Assembly.GetName().Version.ToString(); - } + public static Version GetVersion() + => typeof(SKBitmap).GetTypeInfo().Assembly.GetName().Version; private static bool IsTransparent(SKColor color) - { - - return (color.Red == 255 && color.Green == 255 && color.Blue == 255) || color.Alpha == 0; - } + => (color.Red == 255 && color.Green == 255 && color.Blue == 255) || color.Alpha == 0; public static SKEncodedImageFormat GetImageFormat(ImageFormat selectedFormat) { @@ -130,33 +125,51 @@ namespace Emby.Drawing for (int row = 0; row < bitmap.Height; ++row) { if (IsTransparentRow(bitmap, row)) + { topmost = row + 1; - else break; + } + else + { + break; + } } int bottommost = bitmap.Height; for (int row = bitmap.Height - 1; row >= 0; --row) { if (IsTransparentRow(bitmap, row)) + { bottommost = row; - else break; + } + else + { + break; + } } int leftmost = 0, rightmost = bitmap.Width; for (int col = 0; col < bitmap.Width; ++col) { if (IsTransparentColumn(bitmap, col)) + { leftmost = col + 1; + } else + { break; + } } for (int col = bitmap.Width - 1; col >= 0; --col) { if (IsTransparentColumn(bitmap, col)) + { rightmost = col; + } else + { break; + } } var newRect = SKRectI.Create(leftmost, topmost, rightmost - leftmost, bottommost - topmost); @@ -168,25 +181,19 @@ namespace Emby.Drawing } } - public ImageSize GetImageSize(string path) + public ImageDimensions GetImageSize(string path) { using (var s = new SKFileStream(path)) using (var codec = SKCodec.Create(s)) { var info = codec.Info; - return new ImageSize - { - Width = info.Width, - Height = info.Height - }; + return new ImageDimensions(info.Width, info.Height); } } private static bool HasDiacritics(string text) - { - return !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal); - } + => !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal); private static bool RequiresSpecialCharacterHack(string path) { @@ -212,8 +219,8 @@ namespace Emby.Drawing var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path) ?? string.Empty); - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath)); - fileSystem.CopyFile(path, tempPath, true); + Directory.CreateDirectory(Path.GetDirectoryName(tempPath)); + File.Copy(path, tempPath, true); return tempPath; } @@ -247,9 +254,10 @@ namespace Emby.Drawing } private static string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" }; + internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, ImageOrientation? orientation, out SKEncodedOrigin origin) { - if (!fileSystem.FileExists(path)) + if (!File.Exists(path)) { throw new FileNotFoundException("File not found", path); } @@ -271,7 +279,7 @@ namespace Emby.Drawing var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); // decode - codec.GetPixels(bitmap.Info, bitmap.GetPixels()); + var _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels()); origin = codec.EncodedOrigin; @@ -320,14 +328,11 @@ namespace Emby.Drawing { var bitmap = GetBitmap(path, cropWhitespace, true, orientation, out origin); - if (bitmap != null) + if (bitmap != null && origin != SKEncodedOrigin.TopLeft) { - if (origin != SKEncodedOrigin.TopLeft) + using (bitmap) { - using (bitmap) - { - return OrientImage(bitmap, origin); - } + return OrientImage(bitmap, origin); } } @@ -351,7 +356,6 @@ namespace Emby.Drawing switch (origin) { - case SKEncodedOrigin.TopRight: { var rotated = new SKBitmap(bitmap.Width, bitmap.Height); @@ -370,11 +374,8 @@ namespace Emby.Drawing var rotated = new SKBitmap(bitmap.Width, bitmap.Height); using (var surface = new SKCanvas(rotated)) { - float px = bitmap.Width; - px /= 2; - - float py = bitmap.Height; - py /= 2; + float px = (float)bitmap.Width / 2; + float py = (float)bitmap.Height / 2; surface.RotateDegrees(180, px, py); surface.DrawBitmap(bitmap, 0, 0); @@ -388,11 +389,9 @@ namespace Emby.Drawing var rotated = new SKBitmap(bitmap.Width, bitmap.Height); using (var surface = new SKCanvas(rotated)) { - float px = bitmap.Width; - px /= 2; + float px = (float)bitmap.Width / 2; - float py = bitmap.Height; - py /= 2; + float py = (float)bitmap.Height / 2; surface.Translate(rotated.Width, 0); surface.Scale(-1, 1); @@ -416,7 +415,6 @@ namespace Emby.Drawing surface.RotateDegrees(90); surface.DrawBitmap(bitmap, 0, 0); - } var flippedBitmap = new SKBitmap(rotated.Width, rotated.Height); @@ -481,8 +479,7 @@ namespace Emby.Drawing return rotated; } - default: - return bitmap; + default: return bitmap; } } @@ -492,6 +489,7 @@ namespace Emby.Drawing { throw new ArgumentNullException(nameof(inputPath)); } + if (string.IsNullOrWhiteSpace(inputPath)) { throw new ArgumentNullException(nameof(outputPath)); @@ -511,11 +509,11 @@ namespace Emby.Drawing throw new ArgumentOutOfRangeException(string.Format("Skia unable to read image {0}", inputPath)); } - //_logger.LogInformation("Color type {0}", bitmap.Info.ColorType); - - var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height); + var originalImageSize = new ImageDimensions(bitmap.Width, bitmap.Height); - if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient) + if (!options.CropWhiteSpace + && options.HasDefaultOptions(inputPath, originalImageSize) + && !autoOrient) { // Just spit out the original file if all the options are default return inputPath; @@ -523,10 +521,10 @@ namespace Emby.Drawing var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); - var width = Convert.ToInt32(Math.Round(newImageSize.Width)); - var height = Convert.ToInt32(Math.Round(newImageSize.Height)); + var width = newImageSize.Width; + var height = newImageSize.Height; - using (var resizedBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType)) + using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType)) { // scale image bitmap.ScalePixels(resizedBitmap, SKFilterQuality.High); @@ -534,14 +532,12 @@ namespace Emby.Drawing // If all we're doing is resizing then we can stop now if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); using (var outputStream = new SKFileWStream(outputPath)) + using (var pixmap = new SKPixmap(new SKImageInfo(width, height), resizedBitmap.GetPixels())) { - using (var pixmap = new SKPixmap(new SKImageInfo(width, height), resizedBitmap.GetPixels())) - { - pixmap.Encode(outputStream, skiaOutputFormat, quality); - return outputPath; - } + pixmap.Encode(outputStream, skiaOutputFormat, quality); + return outputPath; } } @@ -588,7 +584,7 @@ namespace Emby.Drawing DrawIndicator(canvas, width, height, options); } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); using (var outputStream = new SKFileWStream(outputPath)) { using (var pixmap = new SKPixmap(new SKImageInfo(width, height), saveBitmap.GetPixels())) @@ -604,8 +600,7 @@ namespace Emby.Drawing public void CreateImageCollage(ImageCollageOptions options) { - double ratio = options.Width; - ratio /= options.Height; + double ratio = (double)options.Width / options.Height; if (ratio >= 1.4) { @@ -617,7 +612,7 @@ namespace Emby.Drawing } else { - // @todo create Poster collage capability + // TODO: Create Poster collage capability new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height); } } @@ -626,7 +621,7 @@ namespace Emby.Drawing { try { - var currentImageSize = new ImageSize(imageWidth, imageHeight); + var currentImageSize = new ImageDimensions(imageWidth, imageHeight); if (options.AddPlayedIndicator) { diff --git a/Emby.Drawing/StripCollageBuilder.cs b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs index dd342998b..92115047c 100644 --- a/Emby.Drawing/StripCollageBuilder.cs +++ b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs @@ -5,7 +5,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using SkiaSharp; -namespace Emby.Drawing +namespace Jellyfin.Drawing.Skia { public class StripCollageBuilder { @@ -43,21 +43,14 @@ namespace Emby.Drawing return SKEncodedImageFormat.Png; } - public void BuildPosterCollage(string[] paths, string outputPath, int width, int height) - { - // @todo - } - public void BuildSquareCollage(string[] paths, string outputPath, int width, int height) { using (var bitmap = BuildSquareCollageBitmap(paths, width, height)) + using (var outputStream = new SKFileWStream(outputPath)) { - using (var outputStream = new SKFileWStream(outputPath)) + using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels())) { - using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels())) - { - pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90); - } + pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90); } } } diff --git a/Emby.Drawing/UnplayedCountIndicator.cs b/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs index 16c084a21..ba712bff7 100644 --- a/Emby.Drawing/UnplayedCountIndicator.cs +++ b/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs @@ -2,13 +2,13 @@ using System.Globalization; using MediaBrowser.Model.Drawing; using SkiaSharp; -namespace Emby.Drawing +namespace Jellyfin.Drawing.Skia { public static class UnplayedCountIndicator { private const int OffsetFromTopRightCorner = 38; - public static void DrawUnplayedCountIndicator(SKCanvas canvas, ImageSize imageSize, int count) + public static void DrawUnplayedCountIndicator(SKCanvas canvas, ImageDimensions imageSize, int count) { var x = imageSize.Width - OffsetFromTopRightCorner; var text = count.ToString(CultureInfo.InvariantCulture); diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 6832fe743..b580f45ca 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,8 +11,8 @@ namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, systemEvents, networkManager) + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, networkManager) { } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 9b698628e..5a4bf5149 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -49,6 +49,7 @@ <ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" /> <ProjectReference Include="..\Emby.IsoMounting\IsoMounter\IsoMounter.csproj" /> <ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" /> + <ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" /> </ItemGroup> </Project> diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index fef7de512..66586d4e4 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -13,6 +13,7 @@ using Emby.Server.Implementations; using Emby.Server.Implementations.EnvironmentInfo; using Emby.Server.Implementations.IO; using Emby.Server.Implementations.Networking; +using Jellyfin.Drawing.Skia; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.Globalization; @@ -96,10 +97,9 @@ namespace Jellyfin.Server fileSystem, environmentInfo, new NullImageEncoder(), - new SystemEvents(), new NetworkManager(_loggerFactory, environmentInfo))) { - await appHost.InitAsync(); + appHost.Init(); appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager); @@ -108,6 +108,7 @@ namespace Jellyfin.Server await appHost.RunStartupTasks(); // TODO: read input for a stop command + try { // Block main thread until shutdown @@ -166,6 +167,7 @@ namespace Jellyfin.Server { Directory.CreateDirectory(programDataPath); } + string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); if (string.IsNullOrEmpty(configDir)) { diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 8ae0ad942..763535129 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -646,7 +646,7 @@ namespace MediaBrowser.Api /// <param name="outputFilePath">The output file path.</param> private void DeleteHlsPartialStreamFiles(string outputFilePath) { - var directory = _fileSystem.GetDirectoryName(outputFilePath); + var directory = Path.GetDirectoryName(outputFilePath); var name = Path.GetFileNameWithoutExtension(outputFilePath); var filesToDelete = _fileSystem.GetFilePaths(directory) diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 0fc20749f..bdd7a8f8f 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -137,14 +137,14 @@ namespace MediaBrowser.Api { if (request.IsFile.Value) { - if (!_fileSystem.FileExists(request.Path)) + if (!File.Exists(request.Path)) { throw new FileNotFoundException("File not found", request.Path); } } else { - if (!_fileSystem.DirectoryExists(request.Path)) + if (!Directory.Exists(request.Path)) { throw new FileNotFoundException("File not found", request.Path); } @@ -153,7 +153,7 @@ namespace MediaBrowser.Api else { - if (!_fileSystem.FileExists(request.Path) && !_fileSystem.DirectoryExists(request.Path)) + if (!File.Exists(request.Path) && !Directory.Exists(request.Path)) { throw new FileNotFoundException("Path not found", request.Path); } @@ -169,7 +169,7 @@ namespace MediaBrowser.Api { var file = Path.Combine(path, Guid.NewGuid().ToString()); - _fileSystem.WriteAllText(file, string.Empty); + File.WriteAllText(file, string.Empty); _fileSystem.DeleteFile(file); } @@ -303,7 +303,7 @@ namespace MediaBrowser.Api public object Get(GetParentPath request) { - var parent = _fileSystem.GetDirectoryName(request.Path); + var parent = Path.GetDirectoryName(request.Path); if (string.IsNullOrEmpty(parent)) { diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs index 61efae46d..fdf584277 100644 --- a/MediaBrowser.Api/Images/ImageByNameService.cs +++ b/MediaBrowser.Api/Images/ImageByNameService.cs @@ -158,7 +158,7 @@ namespace MediaBrowser.Api.Images private string GetThemeName(string path, string rootImagePath) { - var parentName = _fileSystem.GetDirectoryName(path); + var parentName = Path.GetDirectoryName(path); if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase)) { @@ -185,7 +185,7 @@ namespace MediaBrowser.Api.Images var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList(); - var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault(); + var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault(); return _resultFactory.GetStaticFileResult(Request, path); } @@ -199,11 +199,11 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme); - if (_fileSystem.DirectoryExists(themeFolder)) + if (Directory.Exists(themeFolder)) { var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(_fileSystem.FileExists); + .FirstOrDefault(File.Exists); if (!string.IsNullOrEmpty(path)) { @@ -213,14 +213,14 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.RatingsPath, "all"); - if (_fileSystem.DirectoryExists(allFolder)) + if (Directory.Exists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions .Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(_fileSystem.FileExists); + .FirstOrDefault(File.Exists); if (!string.IsNullOrEmpty(path)) { @@ -240,10 +240,10 @@ namespace MediaBrowser.Api.Images { var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme); - if (_fileSystem.DirectoryExists(themeFolder)) + if (Directory.Exists(themeFolder)) { var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i)) - .FirstOrDefault(_fileSystem.FileExists); + .FirstOrDefault(File.Exists); if (!string.IsNullOrEmpty(path)) { @@ -253,13 +253,13 @@ namespace MediaBrowser.Api.Images var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all"); - if (_fileSystem.DirectoryExists(allFolder)) + if (Directory.Exists(allFolder)) { // Avoid implicitly captured closure var currentRequest = request; var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i)) - .FirstOrDefault(_fileSystem.FileExists); + .FirstOrDefault(File.Exists); if (!string.IsNullOrEmpty(path)) { diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 26ac8d40e..149e54f01 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -328,10 +328,9 @@ namespace MediaBrowser.Api.Images var fileInfo = _fileSystem.GetFileInfo(info.Path); length = fileInfo.Length; - var size = _imageProcessor.GetImageSize(item, info, true); - - width = Convert.ToInt32(size.Width); - height = Convert.ToInt32(size.Height); + ImageDimensions size = _imageProcessor.GetImageSize(item, info, true); + width = size.Width; + height = size.Height; if (width <= 0 || height <= 0) { diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 24c8ed835..24d4751c5 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -220,9 +220,9 @@ namespace MediaBrowser.Api.Images try { - contentPath = _fileSystem.ReadAllText(pointerCachePath); + contentPath = File.ReadAllText(pointerCachePath); - if (_fileSystem.FileExists(contentPath)) + if (File.Exists(contentPath)) { return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false); } @@ -239,7 +239,7 @@ namespace MediaBrowser.Api.Images await DownloadImage(request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false); // Read the pointer file again - contentPath = _fileSystem.ReadAllText(pointerCachePath); + contentPath = File.ReadAllText(pointerCachePath); return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false); } @@ -264,7 +264,7 @@ namespace MediaBrowser.Api.Images var fullCachePath = GetFullCachePath(urlHash + "." + ext); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath)); + Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) @@ -273,8 +273,8 @@ namespace MediaBrowser.Api.Images } } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath)); - _fileSystem.WriteAllText(pointerCachePath, fullCachePath); + Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + File.WriteAllText(pointerCachePath, fullCachePath); } } diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 10d882e08..0e7bdc086 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -265,9 +265,9 @@ namespace MediaBrowser.Api try { - contentPath = _fileSystem.ReadAllText(pointerCachePath); + contentPath = File.ReadAllText(pointerCachePath); - if (_fileSystem.FileExists(contentPath)) + if (File.Exists(contentPath)) { return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false); } @@ -284,7 +284,7 @@ namespace MediaBrowser.Api await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false); // Read the pointer file again - contentPath = _fileSystem.ReadAllText(pointerCachePath); + contentPath = File.ReadAllText(pointerCachePath); return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false); } @@ -305,7 +305,7 @@ namespace MediaBrowser.Api var fullCachePath = GetFullCachePath(urlHash + "." + ext); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath)); + Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) @@ -314,8 +314,8 @@ namespace MediaBrowser.Api } } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath)); - _fileSystem.WriteAllText(pointerCachePath, fullCachePath); + Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + File.WriteAllText(pointerCachePath, fullCachePath); } /// <summary> diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index d3009295f..12d807a7e 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -839,7 +839,7 @@ namespace MediaBrowser.Api.Library { try { - _activityManager.CreateAsync(new ActivityLogEntry + _activityManager.Create(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name), Type = "UserDownloadingContent", diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 3be6b29dd..d6bcf7878 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -255,12 +255,12 @@ namespace MediaBrowser.Api.Library var currentPath = Path.Combine(rootFolderPath, request.Name); var newPath = Path.Combine(rootFolderPath, request.NewName); - if (!_fileSystem.DirectoryExists(currentPath)) + if (!Directory.Exists(currentPath)) { throw new FileNotFoundException("The media collection does not exist"); } - if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath)) + if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath)) { throw new ArgumentException("Media library already exists at " + newPath + "."); } @@ -273,11 +273,11 @@ namespace MediaBrowser.Api.Library if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase)) { var tempPath = Path.Combine(rootFolderPath, Guid.NewGuid().ToString("N")); - _fileSystem.MoveDirectory(currentPath, tempPath); + Directory.Move(currentPath, tempPath); currentPath = tempPath; } - _fileSystem.MoveDirectory(currentPath, newPath); + Directory.Move(currentPath, newPath); } finally { diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs index 0694de782..3b2e18852 100644 --- a/MediaBrowser.Api/LocalizationService.cs +++ b/MediaBrowser.Api/LocalizationService.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Api /// Class ParentalRatings /// </summary> [Route("/Localization/Options", "GET", Summary = "Gets localization options")] - public class GetLocalizationOptions : IReturn<LocalizatonOption[]> + public class GetLocalizationOptions : IReturn<LocalizationOption[]> { } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bb525adc7..4ed83baad 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -192,7 +192,7 @@ namespace MediaBrowser.Api.Playback CancellationTokenSource cancellationTokenSource, string workingDirectory = null) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); @@ -258,7 +258,7 @@ namespace MediaBrowser.Api.Playback } var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt"); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath)); + Directory.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, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); @@ -290,7 +290,7 @@ namespace MediaBrowser.Api.Playback new JobLogger(Logger).StartStreamingLog(state, process.StandardError.BaseStream, state.LogFileStream); // Wait for the file to exist before proceeeding - while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) + while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) { await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 1e90d03b0..08a2183f8 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -83,13 +83,13 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; var playlist = state.OutputFilePath; - if (!FileSystem.FileExists(playlist)) + if (!File.Exists(playlist)) { var transcodingLock = ApiEntryPoint.Instance.GetTranscodingLock(playlist); await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (!FileSystem.FileExists(playlist)) + if (!File.Exists(playlist)) { // If the playlist doesn't already exist, startup ffmpeg try @@ -264,7 +264,7 @@ namespace MediaBrowser.Api.Playback.Hls var useGenericSegmenter = true; if (useGenericSegmenter) { - var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); + var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var timeDeltaParam = string.Empty; diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index b3099e17e..30696ec97 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; - if (FileSystem.FileExists(segmentPath)) + if (File.Exists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -177,7 +177,7 @@ namespace MediaBrowser.Api.Playback.Hls try { - if (FileSystem.FileExists(segmentPath)) + if (File.Exists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); transcodingLock.Release(); @@ -381,7 +381,7 @@ namespace MediaBrowser.Api.Playback.Hls private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem) { - var folder = fileSystem.GetDirectoryName(playlist); + var folder = Path.GetDirectoryName(playlist); var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty; @@ -418,7 +418,7 @@ namespace MediaBrowser.Api.Playback.Hls private string GetSegmentPath(StreamState state, string playlist, int index) { - var folder = FileSystem.GetDirectoryName(playlist); + var folder = Path.GetDirectoryName(playlist); var filename = Path.GetFileNameWithoutExtension(playlist); @@ -433,7 +433,7 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob transcodingJob, CancellationToken cancellationToken) { - var segmentFileExists = FileSystem.FileExists(segmentPath); + var segmentFileExists = File.Exists(segmentPath); // If all transcoding has completed, just return immediately if (transcodingJob != null && transcodingJob.HasExited && segmentFileExists) @@ -458,14 +458,14 @@ namespace MediaBrowser.Api.Playback.Hls { try { - var text = FileSystem.ReadAllText(playlistPath, Encoding.UTF8); + var text = File.ReadAllText(playlistPath, Encoding.UTF8); // If it appears in the playlist, it's done if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) { if (!segmentFileExists) { - segmentFileExists = FileSystem.FileExists(segmentPath); + segmentFileExists = File.Exists(segmentPath); } if (segmentFileExists) { @@ -932,7 +932,7 @@ namespace MediaBrowser.Api.Playback.Hls var mapArgs = state.IsOutputVideo ? EncodingHelper.GetMapArgs(state) : string.Empty; - var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); + var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var timeDeltaParam = string.Empty; diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index bb21fe5ae..621d1ff88 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; @@ -153,7 +154,7 @@ namespace MediaBrowser.Api.Playback.Progressive } var outputPath = state.OutputFilePath; - var outputPathExists = FileSystem.FileExists(outputPath); + var outputPathExists = File.Exists(outputPath); var transcodingJob = ApiEntryPoint.Instance.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); var isTranscodeCached = outputPathExists && transcodingJob != null; @@ -377,7 +378,7 @@ namespace MediaBrowser.Api.Playback.Progressive { TranscodingJob job; - if (!FileSystem.FileExists(outputPath)) + if (!File.Exists(outputPath)) { job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 94be45474..af61887b2 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -153,7 +153,11 @@ namespace MediaBrowser.Api private readonly INetworkManager _network; private readonly IDeviceManager _deviceManager; - public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, IInstallationManager installationManager, INetworkManager network, IDeviceManager deviceManager) + public PluginService(IJsonSerializer jsonSerializer, + IApplicationHost appHost, + IInstallationManager installationManager, + INetworkManager network, + IDeviceManager deviceManager) : base() { if (jsonSerializer == null) @@ -173,7 +177,7 @@ namespace MediaBrowser.Api /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public async Task<object> Get(GetRegistrationStatus request) + public object Get(GetRegistrationStatus request) { var record = new MBRegistrationRecord { @@ -187,26 +191,12 @@ namespace MediaBrowser.Api return ToOptimizedResult(record); } - //TODO this function is only kept for compatibility and should be removed once paid plugins break - public async Task<object> Get(GetRegistration request) - { - var info = new RegistrationInfo - { - ExpirationDate = DateTime.Now.AddYears(100), - IsRegistered = true, - IsTrial = false, - Name = request.Name - }; - - return ToOptimizedResult(info); - } - /// <summary> /// Gets the specified request. /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public async Task<object> Get(GetPlugins request) + public object Get(GetPlugins request) { var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray(); return ToOptimizedResult(result); @@ -230,7 +220,7 @@ namespace MediaBrowser.Api /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public async Task<object> Get(GetPluginSecurityInfo request) + public object Get(GetPluginSecurityInfo request) { var result = new PluginSecurityInfo { diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 5f137d804..3d59b4c9a 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -102,7 +102,8 @@ namespace MediaBrowser.Api return new StartupUser { Name = user.Name, - ConnectUserName = user.ConnectUserName + ConnectUserName = user.ConnectUserName, + Password = user.Password }; } @@ -111,8 +112,13 @@ namespace MediaBrowser.Api var user = _userManager.Users.First(); user.Name = request.Name; + _userManager.UpdateUser(user); + if (!string.IsNullOrEmpty(request.Password)) { + await _userManager.ChangePassword(user, request.Password).ConfigureAwait(false); + } + var result = new UpdateStartupUserResult(); return result; @@ -130,6 +136,7 @@ namespace MediaBrowser.Api { public string Name { get; set; } public string ConnectUserName { get; set; } + public string Password { get; set; } } public class UpdateStartupUserResult diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 76f91e373..72a943092 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -267,13 +267,13 @@ namespace MediaBrowser.Api.UserLibrary var session = GetSession(_sessionContext); - var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false); + var dto = UpdatePlayedStatus(user, request.Id, true, datePlayed); foreach (var additionalUserInfo in session.AdditionalUsers) { var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId); - await UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed).ConfigureAwait(false); + UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed); } return dto; @@ -412,13 +412,13 @@ namespace MediaBrowser.Api.UserLibrary var session = GetSession(_sessionContext); - var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false); + var dto = UpdatePlayedStatus(user, request.Id, false, null); foreach (var additionalUserInfo in session.AdditionalUsers) { var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId); - await UpdatePlayedStatus(additionalUser, request.Id, false, null).ConfigureAwait(false); + UpdatePlayedStatus(additionalUser, request.Id, false, null); } return dto; @@ -432,7 +432,7 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="wasPlayed">if set to <c>true</c> [was played].</param> /// <param name="datePlayed">The date played.</param> /// <returns>Task.</returns> - private async Task<UserItemDataDto> UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed) + private UserItemDataDto UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed) { var item = _libraryManager.GetItemById(itemId); diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 9dc625e35..385127c54 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Common /// <summary> /// Inits this instance. /// </summary> - Task InitAsync(); + void Init(); /// <summary> /// Creates the instance. diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index 6e2d5781a..5b8c9da6f 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -44,6 +44,6 @@ namespace MediaBrowser.Controller.Drawing /// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value> bool SupportsImageEncoding { get; } - ImageSize GetImageSize(string path); + ImageDimensions GetImageSize(string path); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 7e6e0127f..783182730 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -26,16 +26,16 @@ namespace MediaBrowser.Controller.Drawing /// <value>The image enhancers.</value> IImageEnhancer[] ImageEnhancers { get; } - ImageSize GetImageSize(string path); + ImageDimensions GetImageSize(string path); /// <summary> /// Gets the size of the image. /// </summary> /// <param name="info">The information.</param> /// <returns>ImageSize.</returns> - ImageSize GetImageSize(BaseItem item, ItemImageInfo info); + ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info); - ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem); + ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem); /// <summary> /// Adds the parts. diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 2680c60bd..432cf8042 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -1,3 +1,4 @@ +using System; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; @@ -6,7 +7,7 @@ namespace MediaBrowser.Controller.Drawing { public static class ImageHelper { - public static ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize) + public static ImageDimensions GetNewImageSize(ImageProcessingOptions options, ImageDimensions? originalImageSize) { if (originalImageSize.HasValue) { @@ -20,26 +21,26 @@ namespace MediaBrowser.Controller.Drawing public static IImageProcessor ImageProcessor { get; set; } - private static ImageSize GetSizeEstimate(ImageProcessingOptions options) + private static ImageDimensions GetSizeEstimate(ImageProcessingOptions options) { if (options.Width.HasValue && options.Height.HasValue) { - return new ImageSize(options.Width.Value, options.Height.Value); + return new ImageDimensions(options.Width.Value, options.Height.Value); } - var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item); + double aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item); - var width = options.Width ?? options.MaxWidth; + int? width = options.Width ?? options.MaxWidth; if (width.HasValue) { - var heightValue = width.Value / aspect; - return new ImageSize(width.Value, heightValue); + int heightValue = Convert.ToInt32((double)width.Value / aspect); + return new ImageDimensions(width.Value, heightValue); } var height = options.Height ?? options.MaxHeight ?? 200; - var widthValue = aspect * height; - return new ImageSize(widthValue, height); + int widthValue = Convert.ToInt32(aspect * height); + return new ImageDimensions(widthValue, height); } private static double GetEstimatedAspectRatio(ImageType type, BaseItem item) @@ -62,7 +63,8 @@ namespace MediaBrowser.Controller.Drawing case ImageType.Logo: return 2.58; case ImageType.Primary: - return item.GetDefaultPrimaryImageAspectRatio(); + double defaultPrimaryImageAspectRatio = item.GetDefaultPrimaryImageAspectRatio(); + return defaultPrimaryImageAspectRatio > 0 ? defaultPrimaryImageAspectRatio : 2.0 / 3; default: return 1; } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index 00d93930f..db432f500 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.Drawing !MaxHeight.HasValue; } - public bool HasDefaultOptions(string originalImagePath, ImageSize? size) + public bool HasDefaultOptions(string originalImagePath, ImageDimensions? size) { if (!size.HasValue) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 5534576f1..482d14e11 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Text; using System.Threading; @@ -228,7 +229,7 @@ namespace MediaBrowser.Controller.Entities return Path; } - return FileSystem.GetDirectoryName(Path); + return System.IO.Path.GetDirectoryName(Path); } } @@ -2208,7 +2209,7 @@ namespace MediaBrowser.Controller.Entities { var allFiles = ImageInfos .Where(i => i.IsLocalFile) - .Select(i => FileSystem.GetDirectoryName(i.Path)) + .Select(i => System.IO.Path.GetDirectoryName(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) .SelectMany(i => directoryService.GetFilePaths(i)) .ToList(); @@ -2235,11 +2236,7 @@ namespace MediaBrowser.Controller.Entities /// </exception> /// <exception cref="ArgumentNullException">item</exception> public string GetImagePath(ImageType imageType, int imageIndex) - { - var info = GetImageInfo(imageType, imageIndex); - - return info == null ? null : info.Path; - } + => GetImageInfo(imageType, imageIndex)?.Path; /// <summary> /// Gets the image information. @@ -2347,7 +2344,7 @@ namespace MediaBrowser.Controller.Entities var newImagePaths = images.Select(i => i.FullName).ToList(); var deleted = existingImages - .Where(i => i.IsLocalFile && !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path)) + .Where(i => i.IsLocalFile && !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !File.Exists(i.Path)) .ToList(); if (deleted.Count > 0) @@ -2400,7 +2397,7 @@ namespace MediaBrowser.Controller.Entities var extensions = new List<string> { ".nfo", ".xml", ".srt", ".vtt", ".sub", ".idx", ".txt", ".edl", ".bif", ".smi", ".ttml" }; extensions.AddRange(SupportedImageExtensions); - return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false) + return FileSystem.GetFiles(System.IO.Path.GetDirectoryName(Path), extensions.ToArray(), false, false) .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase)) .ToList(); } @@ -2512,7 +2509,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path)) { - Name = FileSystem.GetFileNameWithoutExtension(Path); + Name = System.IO.Path.GetFileNameWithoutExtension(Path); hasChanges = true; } diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 82a4531ff..eea1bf43d 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Controller.Entities return new[] { new FileSystemMetadata { - FullName = FileSystem.GetDirectoryName(Path), + FullName = System.IO.Path.GetDirectoryName(Path), IsDirectory = true } }; diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index b40009e0c..5d7c260d1 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Entities.TV return series.Path; } - return FileSystem.GetDirectoryName(Path); + return System.IO.Path.GetDirectoryName(Path); } } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index 10fe096a4..06bae9211 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; @@ -167,18 +168,18 @@ namespace MediaBrowser.Controller.Entities var oldConfigurationDirectory = ConfigurationDirectoryPath; // Exceptions will be thrown if these paths already exist - if (FileSystem.DirectoryExists(newConfigDirectory)) + if (Directory.Exists(newConfigDirectory)) { - FileSystem.DeleteDirectory(newConfigDirectory, true); + Directory.Delete(newConfigDirectory, true); } - if (FileSystem.DirectoryExists(oldConfigurationDirectory)) + if (Directory.Exists(oldConfigurationDirectory)) { - FileSystem.MoveDirectory(oldConfigurationDirectory, newConfigDirectory); + Directory.Move(oldConfigurationDirectory, newConfigDirectory); } else { - FileSystem.CreateDirectory(newConfigDirectory); + Directory.CreateDirectory(newConfigDirectory); } } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 6f98fcd8d..0b0134669 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -508,7 +508,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user, item); + userData = userDataManager.GetUserData(user, item); if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) { diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index dd4440c3b..33a967758 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -345,7 +345,7 @@ namespace MediaBrowser.Controller.Entities { if (IsStacked) { - return FileSystem.GetDirectoryName(Path); + return System.IO.Path.GetDirectoryName(Path); } if (!IsPlaceHolder) diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 7bb8325f8..0222b926e 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Controller.Library return false; } - var parentDir = BaseItem.FileSystem.GetDirectoryName(Path) ?? string.Empty; + var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty; return parentDir.Length > _appPaths.RootFolderPath.Length && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index e086f9d33..fc2b8f9c9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -424,11 +424,9 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream != null && state.VideoStream.Width.HasValue) { // This is hacky but not sure how to get the exact subtitle resolution - double height = state.VideoStream.Width.Value; - height /= 16; - height *= 9; + int height = Convert.ToInt32((double)state.VideoStream.Width.Value / 16.0 * 9.0); - arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), Convert.ToInt32(height).ToString(CultureInfo.InvariantCulture)); + arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), height.ToString(CultureInfo.InvariantCulture)); } var subtitlePath = state.SubtitleStream.Path; @@ -436,7 +434,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase)) { var idxFile = Path.ChangeExtension(subtitlePath, ".idx"); - if (_fileSystem.FileExists(idxFile)) + if (File.Exists(idxFile)) { subtitlePath = idxFile; } @@ -544,7 +542,7 @@ namespace MediaBrowser.Controller.MediaEncoding // var fallbackFontPath = Path.Combine(_appPaths.ProgramDataPath, "fonts", "DroidSansFallback.ttf"); // string fallbackFontParam = string.Empty; - // if (!_fileSystem.FileExists(fallbackFontPath)) + // if (!File.Exists(fallbackFontPath)) // { // _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fallbackFontPath)); // using (var stream = _assemblyInfo.GetManifestResourceStream(GetType(), GetType().Namespace + ".DroidSansFallback.ttf")) @@ -1440,6 +1438,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0) { outputSizeParam = ",format=nv12|vaapi,hwupload"; + + // Add parameters to use VAAPI with burn-in subttiles (GH issue #642) + if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { + outputSizeParam += ",hwmap=mode=read+write+direct"; + } } var videoSizeParam = string.Empty; @@ -1743,6 +1746,12 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add(subParam); + // Ensure proper filters are passed to ffmpeg in case of hardware acceleration via VA-API + // Reference: https://trac.ffmpeg.org/wiki/Hardware/VAAPI + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + filters.Add("hwmap"); + } if (allowTimeStampCopy) { output += " -copyts"; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 6651a6d70..1fe8856cc 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -319,7 +319,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue) { - var size = new ImageSize + var size = new ImageDimensions { Width = VideoStream.Width.Value, Height = VideoStream.Height.Value @@ -331,7 +331,7 @@ namespace MediaBrowser.Controller.MediaEncoding BaseRequest.MaxWidth ?? 0, BaseRequest.MaxHeight ?? 0); - return Convert.ToInt32(newSize.Width); + return newSize.Width; } if (!IsVideoRequest) @@ -349,7 +349,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue) { - var size = new ImageSize + var size = new ImageDimensions { Width = VideoStream.Width.Value, Height = VideoStream.Height.Value @@ -361,7 +361,7 @@ namespace MediaBrowser.Controller.MediaEncoding BaseRequest.MaxWidth ?? 0, BaseRequest.MaxHeight ?? 0); - return Convert.ToInt32(newSize.Height); + return newSize.Height; } if (!IsVideoRequest) diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 969643660..e83260725 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.Playlists if (IsPlaylistFile(path)) { - return FileSystem.GetDirectoryName(path); + return System.IO.Path.GetDirectoryName(path); } return path; diff --git a/MediaBrowser.Controller/Providers/IImageEnhancer.cs b/MediaBrowser.Controller/Providers/IImageEnhancer.cs index 2de657854..c27c00ca2 100644 --- a/MediaBrowser.Controller/Providers/IImageEnhancer.cs +++ b/MediaBrowser.Controller/Providers/IImageEnhancer.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="originalImageSize">Size of the original image.</param> /// <returns>ImageSize.</returns> - ImageSize GetEnhancedImageSize(BaseItem item, ImageType imageType, int imageIndex, ImageSize originalImageSize); + ImageDimensions GetEnhancedImageSize(BaseItem item, ImageType imageType, int imageIndex, ImageDimensions originalImageSize); EnhancedImageInfo GetEnhancedImageInfo(BaseItem item, string inputFile, ImageType imageType, int imageIndex); diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs index 2ee58bbe6..0872335c5 100644 --- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs +++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs @@ -16,11 +16,6 @@ namespace MediaBrowser.Controller.Subtitles event EventHandler<SubtitleDownloadFailureEventArgs> SubtitleDownloadFailure; /// <summary> - /// Occurs when [subtitles downloaded]. - /// </summary> - event EventHandler<SubtitleDownloadEventArgs> SubtitlesDownloaded; - - /// <summary> /// Adds the parts. /// </summary> /// <param name="subtitleProviders">The subtitle providers.</param> diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index 894f46129..443f3fbb5 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -29,11 +30,11 @@ namespace MediaBrowser.LocalMetadata.Images public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) { - var parentPath = _fileSystem.GetDirectoryName(item.Path); + var parentPath = Path.GetDirectoryName(item.Path); var parentPathFiles = directoryService.GetFiles(parentPath); - var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(item.Path); + var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path); return GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles); } diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index e40a55e56..38458e34c 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -102,7 +102,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.ResetPeople(); - using (var fileStream = FileSystem.OpenRead(metadataFile)) + using (var fileStream = File.OpenRead(metadataFile)) { using (var streamReader = new StreamReader(fileStream, encoding)) { diff --git a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs index 537bd073c..acdbb0a29 100644 --- a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.LocalMetadata.Providers var specificFile = Path.ChangeExtension(info.Path, ".xml"); var file = FileSystem.GetFileInfo(specificFile); - return info.IsInMixedFolder || file.Exists ? file : FileSystem.GetFileInfo(Path.Combine(FileSystem.GetDirectoryName(info.Path), "game.xml")); + return info.IsInMixedFolder || file.Exists ? file : FileSystem.GetFileInfo(Path.Combine(Path.GetDirectoryName(info.Path), "game.xml")); } } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 2eac35f28..8a291e6a8 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.LocalMetadata.Savers private void SaveToFile(Stream stream, string path) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index 1af4146bc..bb806ee55 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.MediaEncoding.Configuration && !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath)) { // Validate - if (!_fileSystem.DirectoryExists(newPath)) + if (!Directory.Exists(newPath)) { throw new FileNotFoundException(string.Format("{0} does not exist.", newPath)); } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index ed4c445cd..d3c44f5eb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.MediaEncoding.Encoder .CreateJob(options, EncodingHelper, IsVideoEncoder, progress, cancellationToken).ConfigureAwait(false); encodingJob.OutputFilePath = GetOutputFilePath(encodingJob); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(encodingJob.OutputFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(encodingJob.OutputFilePath)); encodingJob.ReadInputAtNativeFramerate = options.ReadInputAtNativeFramerate; @@ -105,7 +105,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt"); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath)); + Directory.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. encodingJob.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); @@ -137,7 +137,7 @@ namespace MediaBrowser.MediaEncoding.Encoder new JobLogger(Logger).StartStreamingLog(encodingJob, process.StandardError.BaseStream, encodingJob.LogFileStream); // Wait for the file to exist before proceeeding - while (!FileSystem.FileExists(encodingJob.OutputFilePath) && !encodingJob.HasExited) + while (!File.Exists(encodingJob.OutputFilePath) && !encodingJob.HasExited) { await Task.Delay(100, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d9c178431..54344424d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -214,7 +214,7 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ArgumentNullException(nameof(path)); } - if (!FileSystem.FileExists(path) && !FileSystem.DirectoryExists(path)) + if (!File.Exists(path) && !Directory.Exists(path)) { throw new ResourceNotFoundException(); } @@ -288,12 +288,12 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrWhiteSpace(appPath)) { - if (FileSystem.DirectoryExists(appPath)) + if (Directory.Exists(appPath)) { return GetPathsFromDirectory(appPath); } - if (FileSystem.FileExists(appPath)) + if (File.Exists(appPath)) { return new Tuple<string, string>(appPath, GetProbePathFromEncoderPath(appPath)); } @@ -336,7 +336,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); - if (string.IsNullOrWhiteSpace(ffmpegPath) || !FileSystem.FileExists(ffmpegPath)) + if (string.IsNullOrWhiteSpace(ffmpegPath) || !File.Exists(ffmpegPath)) { files = FileSystem.GetFilePaths(path, true); @@ -353,7 +353,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private string GetProbePathFromEncoderPath(string appPath) { - return FileSystem.GetFilePaths(FileSystem.GetDirectoryName(appPath)) + return FileSystem.GetFilePaths(Path.GetDirectoryName(appPath)) .FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase)); } @@ -608,7 +608,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(tempExtractPath)); + Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar @@ -770,7 +770,7 @@ namespace MediaBrowser.MediaEncoding.Encoder vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } - FileSystem.CreateDirectory(targetDirectory); + Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); diff --git a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs index a1d925881..6a5162b8d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs @@ -269,7 +269,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var subLanguageId = NormalizeLanguage(request.Language); string hash; - using (var fileStream = _fileSystem.OpenRead(request.MediaPath)) + using (var fileStream = File.OpenRead(request.MediaPath)) { hash = Utilities.ComputeHash(fileStream); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 2f9eb98ea..d978359c7 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -210,7 +210,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - return _fileSystem.OpenRead(path); + return File.OpenRead(path); } private async Task<SubtitleInfo> GetReadableFile( @@ -386,7 +386,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - if (!_fileSystem.FileExists(outputPath)) + if (!File.Exists(outputPath)) { await ConvertTextSubtitleToSrtInternal(inputPath, language, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false); } @@ -422,7 +422,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(outputPath)); } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); @@ -481,7 +481,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { failed = true; - if (_fileSystem.FileExists(outputPath)) + if (File.Exists(outputPath)) { try { @@ -494,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } } - else if (!_fileSystem.FileExists(outputPath)) + else if (!File.Exists(outputPath)) { failed = true; } @@ -537,7 +537,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - if (!_fileSystem.FileExists(outputPath)) + if (!File.Exists(outputPath)) { await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, outputCodec, outputPath, cancellationToken).ConfigureAwait(false); } @@ -565,7 +565,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(outputPath)); } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, subtitleStreamIndex, outputCodec, outputPath); @@ -634,7 +634,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.LogError(ex, "Error deleting extracted subtitle {Path}", outputPath); } } - else if (!_fileSystem.FileExists(outputPath)) + else if (!File.Exists(outputPath)) { failed = true; } @@ -672,7 +672,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles string text; Encoding encoding; - using (var fileStream = _fileSystem.OpenRead(file)) + using (var fileStream = File.OpenRead(file)) using (var reader = new StreamReader(fileStream, true)) { encoding = reader.CurrentEncoding; @@ -747,7 +747,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } if (protocol == MediaProtocol.File) { - return _fileSystem.ReadAllBytes(path); + return File.ReadAllBytes(path); } throw new ArgumentOutOfRangeException(nameof(protocol)); diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index bbd7b6f2d..897d93d79 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -1,7 +1,6 @@ using System; -using System.Collections.Generic; -using System.Threading.Tasks; using MediaBrowser.Model.Events; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity { @@ -9,8 +8,10 @@ namespace MediaBrowser.Model.Activity { event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated; - Task CreateAsync(ActivityLogEntry entry); + void Create(ActivityLogEntry entry); - IEnumerable<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? x, int? y); + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit); + + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? x, int? y); } } diff --git a/MediaBrowser.Model/Activity/IActivityRepository.cs b/MediaBrowser.Model/Activity/IActivityRepository.cs index 3ed6175ce..f0e3b902c 100644 --- a/MediaBrowser.Model/Activity/IActivityRepository.cs +++ b/MediaBrowser.Model/Activity/IActivityRepository.cs @@ -1,12 +1,12 @@ -using System.Linq; -using System.Threading.Tasks; +using System; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity { public interface IActivityRepository { - Task CreateAsync(ActivityLogEntry entry); + void Create(ActivityLogEntry entry); - IQueryable<ActivityLogEntry> GetActivityLogEntries(); + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? z, int? startIndex, int? limit); } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 522c10980..6d03a03b0 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -953,22 +953,11 @@ namespace MediaBrowser.Model.Dlna if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - var size = new ImageSize - { - Width = videoStream.Width.Value, - Height = videoStream.Height.Value - }; - - double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; - double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); - var newSize = DrawingUtils.Resize(size, - 0, - 0, - maxWidth ?? 0, - maxHeight ?? 0); + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); - return Convert.ToInt32(newSize.Width); + return size.Width; } return MaxWidth; @@ -983,22 +972,11 @@ namespace MediaBrowser.Model.Dlna if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - var size = new ImageSize - { - Width = videoStream.Width.Value, - Height = videoStream.Height.Value - }; - - double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; - double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); - var newSize = DrawingUtils.Resize(size, - 0, - 0, - maxWidth ?? 0, - maxHeight ?? 0); + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); - return Convert.ToInt32(newSize.Height); + return size.Height; } return MaxHeight; diff --git a/MediaBrowser.Model/Drawing/DrawingUtils.cs b/MediaBrowser.Model/Drawing/DrawingUtils.cs index fbd074218..9fe85512f 100644 --- a/MediaBrowser.Model/Drawing/DrawingUtils.cs +++ b/MediaBrowser.Model/Drawing/DrawingUtils.cs @@ -1,3 +1,5 @@ +using System; + namespace MediaBrowser.Model.Drawing { /// <summary> @@ -14,27 +16,25 @@ namespace MediaBrowser.Model.Drawing /// <param name="maxWidth">A max fixed width, if desired</param> /// <param name="maxHeight">A max fixed height, if desired</param> /// <returns>A new size object</returns> - public static ImageSize Resize(ImageSize size, - double width, - double height, - double maxWidth, - double maxHeight) + public static ImageDimensions Resize(ImageDimensions size, + int width, + int height, + int maxWidth, + int maxHeight) { - double newWidth = size.Width; - double newHeight = size.Height; + int newWidth = size.Width; + int newHeight = size.Height; if (width > 0 && height > 0) { newWidth = width; newHeight = height; } - else if (height > 0) { newWidth = GetNewWidth(newHeight, newWidth, height); newHeight = height; } - else if (width > 0) { newHeight = GetNewHeight(newHeight, newWidth, width); @@ -53,7 +53,7 @@ namespace MediaBrowser.Model.Drawing newWidth = maxWidth; } - return new ImageSize { Width = newWidth, Height = newHeight }; + return new ImageDimensions(newWidth, newHeight); } /// <summary> @@ -62,15 +62,9 @@ namespace MediaBrowser.Model.Drawing /// <param name="currentHeight">Height of the current.</param> /// <param name="currentWidth">Width of the current.</param> /// <param name="newHeight">The new height.</param> - /// <returns>System.Double.</returns> - private static double GetNewWidth(double currentHeight, double currentWidth, double newHeight) - { - double scaleFactor = newHeight; - scaleFactor /= currentHeight; - scaleFactor *= currentWidth; - - return scaleFactor; - } + /// <returns>the new width</returns> + private static int GetNewWidth(int currentHeight, int currentWidth, int newHeight) + => Convert.ToInt32((double)newHeight / currentHeight * currentWidth); /// <summary> /// Gets the new height. @@ -79,13 +73,7 @@ namespace MediaBrowser.Model.Drawing /// <param name="currentWidth">Width of the current.</param> /// <param name="newWidth">The new width.</param> /// <returns>System.Double.</returns> - private static double GetNewHeight(double currentHeight, double currentWidth, double newWidth) - { - double scaleFactor = newWidth; - scaleFactor /= currentWidth; - scaleFactor *= currentHeight; - - return scaleFactor; - } + private static int GetNewHeight(int currentHeight, int currentWidth, int newWidth) + => Convert.ToInt32((double)newWidth / currentWidth * currentHeight); } } diff --git a/MediaBrowser.Model/Drawing/ImageSize.cs b/MediaBrowser.Model/Drawing/ImageSize.cs index 87764bbf4..75591d83d 100644 --- a/MediaBrowser.Model/Drawing/ImageSize.cs +++ b/MediaBrowser.Model/Drawing/ImageSize.cs @@ -1,36 +1,23 @@ -using System.Globalization; - namespace MediaBrowser.Model.Drawing { /// <summary> /// Struct ImageSize /// </summary> - public struct ImageSize + public struct ImageDimensions { - private double _height; - private double _width; - /// <summary> /// Gets or sets the height. /// </summary> /// <value>The height.</value> - public double Height - { - get => _height; - set => _height = value; - } + public int Height { get; set; } /// <summary> /// Gets or sets the width. /// </summary> /// <value>The width.</value> - public double Width - { - get => _width; - set => _width = value; - } + public int Width { get; set; } - public bool Equals(ImageSize size) + public bool Equals(ImageDimensions size) { return Width.Equals(size.Width) && Height.Equals(size.Height); } @@ -40,46 +27,10 @@ namespace MediaBrowser.Model.Drawing return string.Format("{0}-{1}", Width, Height); } - public ImageSize(string value) + public ImageDimensions(int width, int height) { - _width = 0; - - _height = 0; - - ParseValue(value); - } - - public ImageSize(int width, int height) - { - _width = width; - _height = height; - } - - public ImageSize(double width, double height) - { - _width = width; - _height = height; - } - - private void ParseValue(string value) - { - if (!string.IsNullOrEmpty(value)) - { - string[] parts = value.Split('-'); - - if (parts.Length == 2) - { - if (double.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) - { - _width = val; - } - - if (double.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out val)) - { - _height = val; - } - } - } + Width = width; + Height = height; } } } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index a2531e504..05efb6681 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Model.Globalization /// Gets the localization options. /// </summary> /// <returns>IEnumerable{LocalizatonOption}.</returns> - LocalizatonOption[] GetLocalizationOptions(); + LocalizationOption[] GetLocalizationOptions(); string RemoveDiacritics(string text); diff --git a/MediaBrowser.Model/Globalization/LocalizationOption.cs b/MediaBrowser.Model/Globalization/LocalizationOption.cs new file mode 100644 index 000000000..c4c9a8919 --- /dev/null +++ b/MediaBrowser.Model/Globalization/LocalizationOption.cs @@ -0,0 +1,14 @@ +namespace MediaBrowser.Model.Globalization +{ + public class LocalizationOption + { + public LocalizationOption(string name, string value) + { + Name = name; + Value = value; + } + + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/MediaBrowser.Model/Globalization/LocalizatonOption.cs b/MediaBrowser.Model/Globalization/LocalizatonOption.cs deleted file mode 100644 index 7fbc8135d..000000000 --- a/MediaBrowser.Model/Globalization/LocalizatonOption.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MediaBrowser.Model.Globalization -{ - public class LocalizatonOption - { - public string Name { get; set; } - public string Value { get; set; } - } -} diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index b8a315ccc..6c9b2bd88 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -36,32 +36,32 @@ namespace MediaBrowser.Model.IO string MakeAbsolutePath(string folderPath, string filePath); /// <summary> - /// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path. + /// Returns a <see cref="FileSystemMetadata" /> object for the specified file or directory path. /// </summary> /// <param name="path">A path to a file or directory.</param> - /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> - /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's - /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and all other properties will reflect the properties of the directory.</remarks> + /// <returns>A <see cref="FileSystemMetadata" /> object.</returns> + /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata" /> object's + /// <see cref="FileSystemMetadata.IsDirectory" /> property will be set to true and all other properties will reflect the properties of the directory.</remarks> FileSystemMetadata GetFileSystemInfo(string path); /// <summary> - /// Returns a <see cref="FileSystemMetadata"/> object for the specified file path. + /// Returns a <see cref="FileSystemMetadata" /> object for the specified file path. /// </summary> /// <param name="path">A path to a file.</param> - /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> - /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's - /// <see cref="FileSystemMetadata.IsDirectory"/> property and the <see cref="FileSystemMetadata.Exists"/> property will both be set to false.</para> - /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> + /// <returns>A <see cref="FileSystemMetadata" /> object.</returns> + /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata" /> object's + /// <see cref="FileSystemMetadata.IsDirectory" /> property and the <see cref="FileSystemMetadata.Exists" /> property will both be set to false.</para> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="M:IFileSystem.GetFileSystemInfo(System.String)" />.</para></remarks> FileSystemMetadata GetFileInfo(string path); /// <summary> - /// Returns a <see cref="FileSystemMetadata"/> object for the specified directory path. + /// Returns a <see cref="FileSystemMetadata" /> object for the specified directory path. /// </summary> /// <param name="path">A path to a directory.</param> - /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> - /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata"/> object's - /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and the <see cref="FileSystemMetadata.Exists"/> property will be set to false.</para> - /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> + /// <returns>A <see cref="FileSystemMetadata" /> object.</returns> + /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata" /> object's + /// <see cref="FileSystemMetadata.IsDirectory" /> property will be set to true and the <see cref="FileSystemMetadata.Exists" /> property will be set to false.</para> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="M:IFileSystem.GetFileSystemInfo(System.String)" />.</para></remarks> FileSystemMetadata GetDirectoryInfo(string path); /// <summary> @@ -110,14 +110,8 @@ namespace MediaBrowser.Model.IO /// <returns>FileStream.</returns> Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false); - Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions); - - /// <summary> - /// Opens the read. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>Stream.</returns> - Stream OpenRead(string path); + Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, + FileOpenOptions fileOpenOptions); string DefaultDirectory { get; } @@ -152,8 +146,6 @@ namespace MediaBrowser.Model.IO /// <returns>System.String.</returns> string NormalizePath(string path); - string GetDirectoryName(string path); - /// <summary> /// Gets the file name without extension. /// </summary> @@ -162,13 +154,6 @@ namespace MediaBrowser.Model.IO string GetFileNameWithoutExtension(FileSystemMetadata info); /// <summary> - /// Gets the file name without extension. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>System.String.</returns> - string GetFileNameWithoutExtension(string path); - - /// <summary> /// Determines whether [is path file] [the specified path]. /// </summary> /// <param name="path">The path.</param> @@ -182,13 +167,6 @@ namespace MediaBrowser.Model.IO void DeleteFile(string path); /// <summary> - /// Deletes the directory. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="recursive">if set to <c>true</c> [recursive].</param> - void DeleteDirectory(string path, bool recursive); - - /// <summary> /// Gets the directories. /// </summary> /// <param name="path">The path.</param> @@ -212,86 +190,6 @@ namespace MediaBrowser.Model.IO IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false); /// <summary> - /// Creates the directory. - /// </summary> - /// <param name="path">The path.</param> - void CreateDirectory(string path); - - /// <summary> - /// Copies the file. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="target">The target.</param> - /// <param name="overwrite">if set to <c>true</c> [overwrite].</param> - void CopyFile(string source, string target, bool overwrite); - - /// <summary> - /// Moves the file. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="target">The target.</param> - void MoveFile(string source, string target); - - /// <summary> - /// Moves the directory. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="target">The target.</param> - void MoveDirectory(string source, string target); - - /// <summary> - /// Directories the exists. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool DirectoryExists(string path); - - /// <summary> - /// Files the exists. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool FileExists(string path); - - /// <summary> - /// Reads all text. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>System.String.</returns> - string ReadAllText(string path); - - byte[] ReadAllBytes(string path); - - void WriteAllBytes(string path, byte[] bytes); - - /// <summary> - /// Writes all text. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="text">The text.</param> - void WriteAllText(string path, string text); - - /// <summary> - /// Writes all text. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="text">The text.</param> - /// <param name="encoding">The encoding.</param> - void WriteAllText(string path, string text, Encoding encoding); - - /// <summary> - /// Reads all text. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="encoding">The encoding.</param> - /// <returns>System.String.</returns> - string ReadAllText(string path, Encoding encoding); - - string[] ReadAllLines(string path); - - void WriteAllLines(string path, IEnumerable<string> lines); - - /// <summary> /// Gets the directory paths. /// </summary> /// <param name="path">The path.</param> @@ -306,6 +204,7 @@ namespace MediaBrowser.Model.IO /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <returns>IEnumerable<System.String>.</returns> IEnumerable<string> GetFilePaths(string path, bool recursive = false); + IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive); /// <summary> @@ -319,15 +218,10 @@ namespace MediaBrowser.Model.IO void SetHidden(string path, bool isHidden); void SetReadOnly(string path, bool readOnly); void SetAttributes(string path, bool isHidden, bool readOnly); - - char DirectorySeparatorChar { get; } - - string GetFullPath(string path); - List<FileSystemMetadata> GetDrives(); - void SetExecutable(string path); } + //TODO Investigate if can be replaced by the one from System.IO ? public enum FileOpenMode { diff --git a/MediaBrowser.Model/System/ISystemEvents.cs b/MediaBrowser.Model/System/ISystemEvents.cs deleted file mode 100644 index 8c47d6fbf..000000000 --- a/MediaBrowser.Model/System/ISystemEvents.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace MediaBrowser.Model.System -{ - public interface ISystemEvents - { - event EventHandler Resume; - event EventHandler Suspend; - event EventHandler SessionLogoff; - event EventHandler SystemShutdown; - } -} diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index a7c2f6d86..57b8d1af8 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -72,7 +72,5 @@ namespace MediaBrowser.Model.Tasks event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting; event EventHandler<TaskCompletionEventArgs> TaskCompleted; - - void RunTaskOnNextStartup(string key); } } diff --git a/MediaBrowser.Model/Tasks/SystemEvent.cs b/MediaBrowser.Model/Tasks/SystemEvent.cs deleted file mode 100644 index 5a3d8a8eb..000000000 --- a/MediaBrowser.Model/Tasks/SystemEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace MediaBrowser.Model.Tasks -{ - /// <summary> - /// Enum SystemEvent - /// </summary> - public enum SystemEvent - { - /// <summary> - /// The wake from sleep - /// </summary> - WakeFromSleep = 0 - } -} diff --git a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs index 80101ec48..714f11872 100644 --- a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs @@ -26,12 +26,6 @@ namespace MediaBrowser.Model.Tasks public long? IntervalTicks { get; set; } /// <summary> - /// Gets or sets the system event. - /// </summary> - /// <value>The system event.</value> - public SystemEvent? SystemEvent { get; set; } - - /// <summary> /// Gets or sets the day of week. /// </summary> /// <value>The day of week.</value> diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index e06d93520..4e41694c4 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.BoxSets var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, preferredMetadataLanguage); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _json.SerializeToFile(mainResult, dataFilePath); } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index d0d00ef12..dee473374 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -233,14 +233,14 @@ namespace MediaBrowser.Providers.Manager { _logger.LogDebug("Saving image to {0}", path); - var parentFolder = _fileSystem.GetDirectoryName(path); + var parentFolder = Path.GetDirectoryName(path); try { _libraryMonitor.ReportFileSystemChangeBeginning(path); _libraryMonitor.ReportFileSystemChangeBeginning(parentFolder); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.SetAttributes(path, false, false); @@ -411,7 +411,7 @@ namespace MediaBrowser.Providers.Manager filename = item is MusicAlbum ? "cdart" : "disc"; break; case ImageType.Primary: - filename = saveLocally && item is Episode ? _fileSystem.GetFileNameWithoutExtension(item.Path) : folderName; + filename = saveLocally && item is Episode ? Path.GetFileNameWithoutExtension(item.Path) : folderName; break; case ImageType.Backdrop: filename = GetBackdropSaveFilename(item.GetImages(type), "backdrop", "backdrop", imageIndex); @@ -437,7 +437,7 @@ namespace MediaBrowser.Providers.Manager { if (type == ImageType.Primary && item is Episode) { - path = Path.Combine(_fileSystem.GetDirectoryName(item.Path), "metadata", filename + extension); + path = Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename + extension); } else if (item.IsInMixedFolder) @@ -471,7 +471,7 @@ namespace MediaBrowser.Providers.Manager return zeroIndexFilename; } - var filenames = images.Select(i => _fileSystem.GetFileNameWithoutExtension(i.Path)).ToList(); + var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList(); var current = 1; while (filenames.Contains(numberedIndexPrefix + current.ToString(UsCulture), StringComparer.OrdinalIgnoreCase)) @@ -569,9 +569,9 @@ namespace MediaBrowser.Providers.Manager if (item is Episode) { - var seasonFolder = _fileSystem.GetDirectoryName(item.Path); + var seasonFolder = Path.GetDirectoryName(item.Path); - var imageFilename = _fileSystem.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension; + var imageFilename = Path.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension; return new[] { Path.Combine(seasonFolder, imageFilename) }; } @@ -617,9 +617,9 @@ namespace MediaBrowser.Providers.Manager { imageFilename = "poster"; } - var folder = _fileSystem.GetDirectoryName(item.Path); + var folder = Path.GetDirectoryName(item.Path); - return Path.Combine(folder, _fileSystem.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension); + return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension); } } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index c2e53ae6c..493c97b6e 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -387,7 +387,7 @@ namespace MediaBrowser.Providers.Manager var existing = item.GetImageInfo(type, 0); if (existing != null) { - if (existing.IsLocalFile && !_fileSystem.FileExists(existing.Path)) + if (existing.IsLocalFile && !File.Exists(existing.Path)) { item.RemoveImage(existing); changed = true; diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 65364ad67..eda5163f0 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -703,7 +703,7 @@ namespace MediaBrowser.Providers.Manager // Manual edit occurred // Even if save local is off, save locally anyway if the metadata file already exists - if (fileSaver == null || !_fileSystem.FileExists(fileSaver.GetSavePath(item))) + if (fileSaver == null || !File.Exists(fileSaver.GetSavePath(item))) { return false; } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 0b902ccec..61a8a122b 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -58,9 +58,9 @@ namespace MediaBrowser.Providers.MediaInfo { var path = GetAudioImagePath(item); - if (!_fileSystem.FileExists(path)) + if (!File.Exists(path)) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? @@ -70,7 +70,7 @@ namespace MediaBrowser.Providers.MediaInfo var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false); - _fileSystem.CopyFile(tempFile, path, true); + File.Copy(tempFile, path, true); try { diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 5e9824ed1..afc760dd4 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -196,7 +197,7 @@ namespace MediaBrowser.Providers.MediaInfo private void FetchShortcutInfo(BaseItem item) { - item.ShortcutPath = _fileSystem.ReadAllLines(item.Path) + item.ShortcutPath = File.ReadAllLines(item.Path) .Select(NormalizeStrmLine) .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith("#", StringComparison.OrdinalIgnoreCase)); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 80c93f157..d2abd2a63 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -175,6 +175,7 @@ namespace MediaBrowser.Providers.MediaInfo { video.RunTimeTicks = mediaInfo.RunTimeTicks; } + video.Size = mediaInfo.Size; if (video.VideoType == VideoType.VideoFile) { diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index 2ce10b656..b6f862f9a 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -98,7 +98,7 @@ namespace MediaBrowser.Providers.MediaInfo int startIndex, string[] files) { - var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(videoPath); + var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoPath); videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension); foreach (var fullName in files) @@ -110,7 +110,7 @@ namespace MediaBrowser.Providers.MediaInfo continue; } - var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(fullName); + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName); fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension); if (!string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) && diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index 63d99db9b..4a94bcb1a 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -254,7 +254,7 @@ namespace MediaBrowser.Providers.Movies var path = GetFanartJsonPath(id); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); try { diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index 10d3e5e9d..4300b84a9 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Net; using System.Threading; @@ -91,7 +92,7 @@ namespace MediaBrowser.Providers.Movies tmdbId = movieInfo.id.ToString(_usCulture); dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(movieInfo, dataFilePath); } } diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index f03a8c2c2..c5af5ef36 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -198,7 +198,7 @@ namespace MediaBrowser.Providers.Movies var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(mainResult, dataFilePath); } diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs index 3c4855806..7ccf7cffa 100644 --- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs @@ -153,7 +153,7 @@ namespace MediaBrowser.Providers.Music var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions { diff --git a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs index 03eefc2eb..2540a6047 100644 --- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs @@ -151,7 +151,7 @@ namespace MediaBrowser.Providers.Music { using (var response = httpResponse.Content) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) { diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index a7456bdc0..2efeb6985 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -233,7 +233,7 @@ namespace MediaBrowser.Providers.Music var jsonPath = GetArtistJsonPath(_config.ApplicationPaths, musicBrainzId); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(jsonPath)); + Directory.CreateDirectory(Path.GetDirectoryName(jsonPath)); try { diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index ecae0c39d..e4bb52217 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -510,13 +510,11 @@ namespace MediaBrowser.Providers.Music return new ValueTuple<string, string>(); } - private static ValueTuple<string, string> ParseArtistNameCredit(XmlReader reader) + private static (string, string) ParseArtistNameCredit(XmlReader reader) { reader.MoveToContent(); reader.Read(); - string name = null; - // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator // Loop through each element @@ -547,7 +545,7 @@ namespace MediaBrowser.Providers.Music } } - return new ValueTuple<string, string>(name, null); + return (null, null); } private static ValueTuple<string, string> ParseArtistArtistCredit(XmlReader reader, string artistId) diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs index c52907745..19dce34d6 100644 --- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs @@ -294,7 +294,7 @@ namespace MediaBrowser.Providers.Omdb using (var stream = response.Content) { var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(rootObject, path); } } @@ -331,7 +331,7 @@ namespace MediaBrowser.Providers.Omdb using (var stream = response.Content) { var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(rootObject, path); } } diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index dc6ce842e..6d9d66f80 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -229,7 +229,7 @@ namespace MediaBrowser.Providers.People { using (var json = response.Content) { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) { diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index 7a57adb33..dacb63f84 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.Playlists return Task.FromResult(ItemUpdateType.None); } - using (var stream = _fileSystem.OpenRead(path)) + using (var stream = File.OpenRead(path)) { var items = GetItems(stream, extension).ToArray(); diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 481f0d01f..4b41589f1 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -151,11 +151,11 @@ namespace MediaBrowser.Providers.Studios }).ConfigureAwait(false); - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(file)); + Directory.CreateDirectory(Path.GetDirectoryName(file)); try { - fileSystem.CopyFile(temp, file, true); + File.Copy(temp, file, true); } catch { diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 468ba730a..e247c4f86 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -30,9 +30,7 @@ namespace MediaBrowser.Providers.Subtitles private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _monitor; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IServerConfigurationManager _config; - public event EventHandler<SubtitleDownloadEventArgs> SubtitlesDownloaded; public event EventHandler<SubtitleDownloadFailureEventArgs> SubtitleDownloadFailure; private ILocalizationManager _localization; @@ -42,14 +40,12 @@ namespace MediaBrowser.Providers.Subtitles IFileSystem fileSystem, ILibraryMonitor monitor, IMediaSourceManager mediaSourceManager, - IServerConfigurationManager config, ILocalizationManager localizationManager) { _logger = loggerFactory.CreateLogger(nameof(SubtitleManager)); _fileSystem = fileSystem; _monitor = monitor; _mediaSourceManager = mediaSourceManager; - _config = config; _localization = localizationManager; } @@ -134,11 +130,6 @@ namespace MediaBrowser.Providers.Subtitles return results.SelectMany(i => i).ToArray(); } - private SubtitleOptions GetOptions() - { - return _config.GetConfiguration<SubtitleOptions>("subtitles"); - } - public Task DownloadSubtitles(Video video, string subtitleId, CancellationToken cancellationToken) { var libraryOptions = BaseItem.LibraryManager.GetLibraryOptions(video); @@ -168,7 +159,7 @@ namespace MediaBrowser.Providers.Subtitles memoryStream.Position = 0; var savePaths = new List<string>(); - var saveFileName = _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower(); + var saveFileName = Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower(); if (response.IsForced) { @@ -217,7 +208,7 @@ namespace MediaBrowser.Providers.Subtitles try { - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(savePath)); + Directory.CreateDirectory(Path.GetDirectoryName(savePath)); using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) { diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs index 7f3bc323e..172a7d2b8 100644 --- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs @@ -298,7 +298,7 @@ namespace MediaBrowser.Providers.TV var path = GetFanartJsonPath(tvdbId); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); try { diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 8da6d4523..4ac012399 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.TV } // Check this in order to avoid logging an exception due to directory not existing - if (!_fileSystem.DirectoryExists(seriesDataPath)) + if (!Directory.Exists(seriesDataPath)) { return false; } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs index 3df3cf8b8..9f1102946 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Providers.TV var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(mainResult, dataFilePath); } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs index 8d13cc726..790b38074 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs @@ -188,7 +188,7 @@ namespace MediaBrowser.Providers.TV var dataFilePath = GetDataFilePath(id, seasonNumber, preferredMetadataLanguage); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(mainResult, dataFilePath); } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index c20cbc419..76031a7cd 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.TV tmdbId = seriesInfo.id.ToString(_usCulture); string dataFilePath = GetDataFilePath(tmdbId, language); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(seriesInfo, dataFilePath); await EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false); @@ -351,7 +351,7 @@ namespace MediaBrowser.Providers.TV var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); + Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(mainResult, dataFilePath); } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index c4edb43ff..25fc214b5 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -197,7 +197,7 @@ namespace MediaBrowser.Providers.TV if (searchInfo.IndexNumber.HasValue) { - var files = GetEpisodeXmlFiles(searchInfo.SeriesDisplayOrder, searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, _fileSystem.GetDirectoryName(xmlFile)); + var files = GetEpisodeXmlFiles(searchInfo.SeriesDisplayOrder, searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, Path.GetDirectoryName(xmlFile)); list = files.Select(GetXmlReader).ToList(); } @@ -296,7 +296,7 @@ namespace MediaBrowser.Providers.TV private XmlReader GetXmlReader(FileSystemMetadata xmlFile) { - return GetXmlReader(_fileSystem.ReadAllText(xmlFile.FullName, Encoding.UTF8)); + return GetXmlReader(File.ReadAllText(xmlFile.FullName, Encoding.UTF8)); } private XmlReader GetXmlReader(string xml) diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs index c4a132d45..6f7cb72d3 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Providers.TV { var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); - _fileSystem.CreateDirectory(path); + Directory.CreateDirectory(path); var timestampFile = Path.Combine(path, "time.txt"); @@ -95,7 +95,7 @@ namespace MediaBrowser.Providers.TV } // Find out the last time we queried tvdb for updates - var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; + var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; string newUpdateTime; @@ -171,7 +171,7 @@ namespace MediaBrowser.Providers.TV await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false); } - _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); + File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); progress.Report(100); } @@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.TV seriesDataPath = Path.Combine(seriesDataPath, id); - _fileSystem.CreateDirectory(seriesDataPath); + Directory.CreateDirectory(seriesDataPath); return TvdbSeriesProvider.Current.DownloadSeriesZip(id, MetadataProviders.Tvdb.ToString(), null, null, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken); } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index b6df64396..496e0bb72 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -263,7 +263,7 @@ namespace MediaBrowser.Providers.TV if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase)) { - _fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true); + File.Copy(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true); } await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false); @@ -1526,7 +1526,7 @@ namespace MediaBrowser.Providers.TV var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber, episodeNumber)); // Only save the file if not already there, or if the episode has changed - if (hasEpisodeChanged || !_fileSystem.FileExists(file)) + if (hasEpisodeChanged || !File.Exists(file)) { using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true)) { @@ -1546,7 +1546,7 @@ namespace MediaBrowser.Providers.TV file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", absoluteNumber)); // Only save the file if not already there, or if the episode has changed - if (hasEpisodeChanged || !_fileSystem.FileExists(file)) + if (hasEpisodeChanged || !File.Exists(file)) { using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true)) { @@ -1567,7 +1567,7 @@ namespace MediaBrowser.Providers.TV file = Path.Combine(seriesDataPath, string.Format("episode-dvd-{0}-{1}.xml", dvdSeasonNumber, dvdEpisodeNumber)); // Only save the file if not already there, or if the episode has changed - if (hasEpisodeChanged || !_fileSystem.FileExists(file)) + if (hasEpisodeChanged || !File.Exists(file)) { using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true)) { diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index db0011114..2f4e21443 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -390,7 +390,7 @@ namespace MediaBrowser.WebDashboard.Api { try { - _fileSystem.DeleteDirectory(targetPath, true); + Directory.Delete(targetPath, true); } catch (IOException) { @@ -435,15 +435,15 @@ namespace MediaBrowser.WebDashboard.Api private void CopyDirectory(string source, string destination) { - _fileSystem.CreateDirectory(destination); + Directory.CreateDirectory(destination); //Now Create all of the directories foreach (var dirPath in _fileSystem.GetDirectories(source, true)) - _fileSystem.CreateDirectory(dirPath.FullName.Replace(source, destination)); + Directory.CreateDirectory(dirPath.FullName.Replace(source, destination)); //Copy all the files & Replaces any files with the same name foreach (var newPath in _fileSystem.GetFiles(source, true)) - _fileSystem.CopyFile(newPath.FullName, newPath.FullName.Replace(source, destination), true); + File.Copy(newPath.FullName, newPath.FullName.Replace(source, destination), true); } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 513296745..f20dbbb6e 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers { if (!SupportsUrlAfterClosingXmlTag) { - using (var fileStream = FileSystem.OpenRead(metadataFile)) + using (var fileStream = File.OpenRead(metadataFile)) { using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { @@ -140,7 +140,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers return; } - using (var fileStream = FileSystem.OpenRead(metadataFile)) + using (var fileStream = File.OpenRead(metadataFile)) { using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index c76f8345a..a8cb6ac40 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected override void Fetch(MetadataResult<Episode> item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken) { - using (var fileStream = FileSystem.OpenRead(metadataFile)) + using (var fileStream = File.OpenRead(metadataFile)) { using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 1efffff3d..96b906b3c 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -193,7 +193,7 @@ namespace MediaBrowser.XbmcMetadata.Savers private void SaveToFile(Stream stream, string path) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)); // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); @@ -974,7 +974,7 @@ namespace MediaBrowser.XbmcMetadata.Savers settings.IgnoreProcessingInstructions = true; settings.IgnoreComments = true; - using (var fileStream = fileSystem.OpenRead(path)) + using (var fileStream = File.OpenRead(path)) { using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs index 102fba70b..5246bec02 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return false; } - return updateType >= MinimumUpdateType || (updateType >= ItemUpdateType.MetadataImport && FileSystem.FileExists(GetSavePath(item))); + return updateType >= MinimumUpdateType || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item))); } protected override void WriteCustomElements(BaseItem item, XmlWriter writer) diff --git a/MediaBrowser.sln b/MediaBrowser.sln index dfaa2601f..62ae58d73 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26730.3 MinimumVisualStudioVersion = 10.0.40219.1 @@ -56,6 +56,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution SharedVersion.cs = SharedVersion.cs EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Drawing.Skia", "Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj", "{154872D9-6C12-4007-96E3-8F70A58386CE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -158,6 +160,10 @@ Global {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.Build.0 = Release|Any CPU + {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SocketHttpListener/Net/HttpListenerContext.Managed.cs b/SocketHttpListener/Net/HttpListenerContext.Managed.cs index 29b0a7ae2..79742bf37 100644 --- a/SocketHttpListener/Net/HttpListenerContext.Managed.cs +++ b/SocketHttpListener/Net/HttpListenerContext.Managed.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Security.Principal; using System.Text; @@ -7,7 +7,7 @@ using SocketHttpListener.Net.WebSockets; namespace SocketHttpListener.Net { - public sealed unsafe partial class HttpListenerContext + public sealed partial class HttpListenerContext { private HttpConnection _connection; diff --git a/SocketHttpListener/Net/HttpListenerContext.cs b/SocketHttpListener/Net/HttpListenerContext.cs index 8045299c6..d84e2d1aa 100644 --- a/SocketHttpListener/Net/HttpListenerContext.cs +++ b/SocketHttpListener/Net/HttpListenerContext.cs @@ -6,7 +6,7 @@ using SocketHttpListener.Net.WebSockets; namespace SocketHttpListener.Net { - public sealed unsafe partial class HttpListenerContext + public sealed partial class HttpListenerContext { private HttpListenerResponse _response; private IPrincipal _user; diff --git a/SocketHttpListener/Net/HttpListenerRequest.cs b/SocketHttpListener/Net/HttpListenerRequest.cs index 4924a7fa8..faeca78b2 100644 --- a/SocketHttpListener/Net/HttpListenerRequest.cs +++ b/SocketHttpListener/Net/HttpListenerRequest.cs @@ -8,7 +8,7 @@ using SocketHttpListener.Net.WebSockets; namespace SocketHttpListener.Net { - public sealed unsafe partial class HttpListenerRequest + public sealed partial class HttpListenerRequest { private CookieCollection _cookies; private bool? _keepAlive; diff --git a/SocketHttpListener/Net/HttpListenerResponse.cs b/SocketHttpListener/Net/HttpListenerResponse.cs index a32aca043..66ef88564 100644 --- a/SocketHttpListener/Net/HttpListenerResponse.cs +++ b/SocketHttpListener/Net/HttpListenerResponse.cs @@ -5,7 +5,7 @@ using System.Text; namespace SocketHttpListener.Net { - public sealed unsafe partial class HttpListenerResponse : IDisposable + public sealed partial class HttpListenerResponse : IDisposable { private BoundaryType _boundaryType = BoundaryType.None; private CookieCollection _cookies; diff --git a/SocketHttpListener/Net/WebHeaderEncoding.cs b/SocketHttpListener/Net/WebHeaderEncoding.cs index b65ff3c0d..96e0cc85d 100644 --- a/SocketHttpListener/Net/WebHeaderEncoding.cs +++ b/SocketHttpListener/Net/WebHeaderEncoding.cs @@ -71,7 +71,7 @@ namespace SocketHttpListener.Net } } } - internal static unsafe byte[] GetBytes(string myString) + internal static byte[] GetBytes(string myString) { byte[] bytes = new byte[myString.Length]; if (myString.Length != 0) |
