From 1603d1928e888abeccc6a5fab2e1f13aa65eea6c Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 10 Sep 2021 09:29:14 +0200 Subject: Kill ProgressiveFileCopier and seek to end for ongoing livetv --- .../Library/ExclusiveLiveStream.cs | 6 ++ .../Library/MediaSourceManager.cs | 18 ++-- .../LiveTv/EmbyTV/DirectRecorder.cs | 16 ++- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 7 +- .../LiveTv/TunerHosts/LiveStream.cs | 117 ++++----------------- .../LiveTv/TunerHosts/SharedHttpStream.cs | 49 +++------ 6 files changed, 64 insertions(+), 149 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs index 6c65b58999..9ba9f2115e 100644 --- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs +++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs @@ -4,6 +4,7 @@ using System; using System.Globalization; +using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; @@ -41,6 +42,11 @@ namespace Emby.Server.Implementations.Library return _closeFn(); } + public Stream GetStream(bool seekNearEnd) + { + throw new NotSupportedException(); + } + public Task Open(CancellationToken openCancellationToken) { return Task.CompletedTask; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 6f83973ba1..8e4b32a9c9 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -602,7 +602,7 @@ namespace Emby.Server.Implementations.Library public async Task GetLiveStreamMediaInfo(string id, CancellationToken cancellationToken) { - var liveStreamInfo = await GetLiveStreamInfo(id, cancellationToken).ConfigureAwait(false); + var liveStreamInfo = GetLiveStreamInfo(id); var mediaSource = liveStreamInfo.MediaSource; @@ -771,18 +771,18 @@ namespace Emby.Server.Implementations.Library mediaSource.InferTotalBitrate(true); } - public async Task> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken) + public Task> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(id)) { throw new ArgumentNullException(nameof(id)); } - var info = await GetLiveStreamInfo(id, cancellationToken).ConfigureAwait(false); - return new Tuple(info.MediaSource, info as IDirectStreamProvider); + var info = GetLiveStreamInfo(id); + return Task.FromResult(new Tuple(info.MediaSource, info as IDirectStreamProvider)); } - private Task GetLiveStreamInfo(string id, CancellationToken cancellationToken) + public ILiveStream GetLiveStreamInfo(string id) { if (string.IsNullOrEmpty(id)) { @@ -791,12 +791,10 @@ namespace Emby.Server.Implementations.Library if (_openStreams.TryGetValue(id, out ILiveStream info)) { - return Task.FromResult(info); - } - else - { - return Task.FromException(new ResourceNotFoundException()); + return info; } + + throw new ResourceNotFoundException(); } public async Task GetLiveStream(string id, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index c5a9a92ec2..fdefa2679a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -5,6 +5,7 @@ using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Helpers; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; @@ -50,16 +51,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { onStarted(); - _logger.LogInformation("Copying recording stream to file {0}", targetFile); + _logger.LogInformation("Copying recording to file {FilePath}", targetFile); // The media source is infinite so we need to handle stopping ourselves using var durationToken = new CancellationTokenSource(duration); using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token); - - await directStreamProvider.CopyToAsync(output, cancellationTokenSource.Token).ConfigureAwait(false); + var linkedCancellationToken = cancellationTokenSource.Token; + + await using var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream(), null, null); + await _streamHelper.CopyToAsync( + fileStream, + output, + IODefaults.CopyToBufferSize, + 1000, + linkedCancellationToken).ConfigureAwait(false); } - _logger.LogInformation("Recording completed to file {0}", targetFile); + _logger.LogInformation("Recording completed: {FilePath}", targetFile); } private async Task RecordFromMediaSource(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 58e0c7448a..a8f761fdeb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -156,11 +156,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await taskCompletionSource.Task.ConfigureAwait(false); } - public string GetFilePath() - { - return TempFilePath; - } - private async Task StartStreaming(UdpClient udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) { using (udpClient) @@ -184,7 +179,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun EnableStreamSharing = false; } - await DeleteTempFiles(new List { TempFilePath }).ConfigureAwait(false); + await DeleteTempFiles(TempFilePath).ConfigureAwait(false); } private async Task CopyTo(UdpClient udpClient, string file, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 2c21a4a893..4f9d343276 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -3,10 +3,8 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -97,6 +95,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.CompletedTask; } + public Stream GetStream(bool seekNearEnd = true) + { + var stream = GetInputStream(TempFilePath, AsyncFile.UseAsyncIO); + bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; + if (seekFile) + { + TrySeek(stream, -20000); + } + + return stream; + } + protected FileStream GetInputStream(string path, bool allowAsyncFileRead) => new FileStream( path, @@ -106,112 +116,29 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts IODefaults.FileStreamBufferSize, allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan); - public Task DeleteTempFiles() - { - return DeleteTempFiles(GetStreamFilePaths()); - } - - protected async Task DeleteTempFiles(IEnumerable paths, int retryCount = 0) + protected async Task DeleteTempFiles(string path, int retryCount = 0) { if (retryCount == 0) { - Logger.LogInformation("Deleting temp files {0}", paths); - } - - var failedFiles = new List(); - - foreach (var path in paths) - { - if (!File.Exists(path)) - { - continue; - } - - try - { - FileSystem.DeleteFile(path); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error deleting file {path}", path); - failedFiles.Add(path); - } - } - - if (failedFiles.Count > 0 && retryCount <= 40) - { - await Task.Delay(500).ConfigureAwait(false); - await DeleteTempFiles(failedFiles, retryCount + 1).ConfigureAwait(false); + Logger.LogInformation("Deleting temp file {FilePath}", path); } - } - protected virtual List GetStreamFilePaths() - { - return new List { TempFilePath }; - } - - public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken) - { - using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token); - cancellationToken = linkedCancellationTokenSource.Token; - - bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; - - var nextFileInfo = GetNextFile(null); - var nextFile = nextFileInfo.file; - var isLastFile = nextFileInfo.isLastFile; - - var allowAsync = AsyncFile.UseAsyncIO; - while (!string.IsNullOrEmpty(nextFile)) - { - var emptyReadLimit = isLastFile ? EmptyReadLimit : 1; - - await CopyFile(nextFile, seekFile, emptyReadLimit, allowAsync, stream, cancellationToken).ConfigureAwait(false); - - seekFile = false; - nextFileInfo = GetNextFile(nextFile); - nextFile = nextFileInfo.file; - isLastFile = nextFileInfo.isLastFile; - } - - Logger.LogInformation("Live Stream ended."); - } - - private (string file, bool isLastFile) GetNextFile(string currentFile) - { - var files = GetStreamFilePaths(); - - if (string.IsNullOrEmpty(currentFile)) + try { - return (files[^1], true); + FileSystem.DeleteFile(path); } - - var nextIndex = files.FindIndex(i => string.Equals(i, currentFile, StringComparison.OrdinalIgnoreCase)) + 1; - - var isLastFile = nextIndex == files.Count - 1; - - return (files.ElementAtOrDefault(nextIndex), isLastFile); - } - - private async Task CopyFile(string path, bool seekFile, int emptyReadLimit, bool allowAsync, Stream stream, CancellationToken cancellationToken) - { - using (var inputStream = GetInputStream(path, allowAsync)) + catch (Exception ex) { - if (seekFile) + Logger.LogError(ex, "Error deleting file {FilePath}", path); + if (retryCount <= 40) { - TrySeek(inputStream, -20000); + await Task.Delay(500).ConfigureAwait(false); + await DeleteTempFiles(path, retryCount + 1).ConfigureAwait(false); } - - await StreamHelper.CopyToAsync( - inputStream, - stream, - IODefaults.CopyToBufferSize, - emptyReadLimit, - cancellationToken).ConfigureAwait(false); } } - private void TrySeek(FileStream stream, long offset) + private void TrySeek(Stream stream, long offset) { if (!stream.CanSeek) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 8629938777..84a878e517 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -3,7 +3,6 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net.Http; @@ -55,39 +54,26 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); var typeName = GetType().Name; - Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url); + Logger.LogInformation("Opening {StreamType} Live stream from {Url}", typeName, url); // Response stream is disposed manually. var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None) .ConfigureAwait(false); - var extension = "ts"; - var requiresRemux = false; - var contentType = response.Content.Headers.ContentType?.ToString() ?? string.Empty; - if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1) - { - requiresRemux = true; - } - else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 || - contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 || - contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1 || - contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1) - { - requiresRemux = true; - } - - // Close the stream without any sharing features - if (requiresRemux) + if (contentType.Contains("matroska", StringComparison.OrdinalIgnoreCase) + || contentType.Contains("mp4", StringComparison.OrdinalIgnoreCase) + || contentType.Contains("dash", StringComparison.OrdinalIgnoreCase) + || contentType.Contains("mpegURL", StringComparison.OrdinalIgnoreCase) + || contentType.Contains("text/", StringComparison.OrdinalIgnoreCase)) { - using (response) - { - return; - } + // Close the stream without any sharing features + response.Dispose(); + return; } - SetTempFilePath(extension); + SetTempFilePath("ts"); var taskCompletionSource = new TaskCompletionSource(); @@ -117,16 +103,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!taskCompletionSource.Task.Result) { - Logger.LogWarning("Zero bytes copied from stream {0} to {1} but no exception raised", GetType().Name, TempFilePath); + Logger.LogWarning("Zero bytes copied from stream {StreamType} to {FilePath} but no exception raised", GetType().Name, TempFilePath); throw new EndOfStreamException(string.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name)); } } - public string GetFilePath() - { - return TempFilePath; - } - private Task StartStreaming(HttpResponseMessage response, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) { return Task.Run( @@ -134,7 +115,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); + Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); @@ -147,19 +128,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (OperationCanceledException ex) { - Logger.LogInformation("Copying of {0} to {1} was canceled", GetType().Name, TempFilePath); + Logger.LogInformation("Copying of {StreamType} to {FilePath} was canceled", GetType().Name, TempFilePath); openTaskCompletionSource.TrySetException(ex); } catch (Exception ex) { - Logger.LogError(ex, "Error copying live stream {0} to {1}.", GetType().Name, TempFilePath); + Logger.LogError(ex, "Error copying live stream {StreamType} to {FilePath}", GetType().Name, TempFilePath); openTaskCompletionSource.TrySetException(ex); } openTaskCompletionSource.TrySetResult(false); EnableStreamSharing = false; - await DeleteTempFiles(new List { TempFilePath }).ConfigureAwait(false); + await DeleteTempFiles(TempFilePath).ConfigureAwait(false); }, CancellationToken.None); } -- cgit v1.2.3 From f3573b061c4d9eb869316ce3de320fd8803aeef8 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 10 Sep 2021 09:56:48 +0200 Subject: Remove the unused arg --- Emby.Server.Implementations/Library/ExclusiveLiveStream.cs | 2 +- Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs | 2 +- MediaBrowser.Controller/Library/IDirectStreamProvider.cs | 5 ++--- MediaBrowser.Controller/Library/ILiveStream.cs | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs index 9ba9f2115e..868071a992 100644 --- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs +++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs @@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Library return _closeFn(); } - public Stream GetStream(bool seekNearEnd) + public Stream GetStream() { throw new NotSupportedException(); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 4f9d343276..817b1f8046 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.CompletedTask; } - public Stream GetStream(bool seekNearEnd = true) + public Stream GetStream() { var stream = GetInputStream(TempFilePath, AsyncFile.UseAsyncIO); bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; diff --git a/MediaBrowser.Controller/Library/IDirectStreamProvider.cs b/MediaBrowser.Controller/Library/IDirectStreamProvider.cs index 2939668f7d..96f8b7eba9 100644 --- a/MediaBrowser.Controller/Library/IDirectStreamProvider.cs +++ b/MediaBrowser.Controller/Library/IDirectStreamProvider.cs @@ -11,10 +11,9 @@ namespace MediaBrowser.Controller.Library public interface IDirectStreamProvider { /// - /// Gets the live stream, optionally seeks to the end of the file first. + /// Gets the live stream, shared streams seek to the end of the file first. /// - /// A value indicating whether to seek to the end of the file. /// The stream. - Stream GetStream(bool seekNearEnd = true); + Stream GetStream(); } } diff --git a/MediaBrowser.Controller/Library/ILiveStream.cs b/MediaBrowser.Controller/Library/ILiveStream.cs index a29a91fe9c..4c44a17fdd 100644 --- a/MediaBrowser.Controller/Library/ILiveStream.cs +++ b/MediaBrowser.Controller/Library/ILiveStream.cs @@ -27,6 +27,6 @@ namespace MediaBrowser.Controller.Library Task Close(); - Stream GetStream(bool seekNearEnd = true); + Stream GetStream(); } } -- cgit v1.2.3 From 1a5a74d2a95506249cf071c659e3c6cf01f28f78 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 10 Sep 2021 10:03:42 +0200 Subject: Remove more unused args --- Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs | 2 +- Jellyfin.Api/Controllers/LiveTvController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 2 +- Jellyfin.Api/Helpers/AudioHelper.cs | 2 +- Jellyfin.Api/Helpers/ProgressiveFileStream.cs | 8 +++----- 5 files changed, 7 insertions(+), 9 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index fdefa2679a..f6e0111b6d 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token); var linkedCancellationToken = cancellationTokenSource.Token; - await using var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream(), null, null); + await using var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream()); await _streamHelper.CopyToAsync( fileStream, output, diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index c3856b882e..3f68b267f3 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1207,7 +1207,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream(), null, _transcodingJobHelper); + var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file." + container)); } diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 0af10ceefa..d7d48ba3e7 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -454,7 +454,7 @@ namespace Jellyfin.Api.Controllers StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); - var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream(), null, _transcodingJobHelper); + var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return File(liveStream, MimeTypes.GetMimeType("file.ts")!); } diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 19da180e53..06f889f085 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -121,7 +121,7 @@ namespace Jellyfin.Api.Helpers StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); - var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream(), null, _transcodingJobHelper); + var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file.ts")); } diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs index 9939734179..c570183514 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs @@ -51,13 +51,11 @@ namespace Jellyfin.Api.Helpers /// Initializes a new instance of the class. /// /// The stream to progressively copy. - /// The transcoding job information. - /// The transcoding job helper. /// The timeout duration in milliseconds. - public ProgressiveFileStream(Stream stream, TranscodingJobDto? job, TranscodingJobHelper? transcodingJobHelper, int timeoutMs = 30000) + public ProgressiveFileStream(Stream stream, int timeoutMs = 30000) { - _job = job; - _transcodingJobHelper = transcodingJobHelper; + _job = null; + _transcodingJobHelper = null; _timeoutMs = timeoutMs; _allowAsyncFileRead = AsyncFile.UseAsyncIO; _stream = stream; -- cgit v1.2.3 From 026a7af0e8cc15f889ba94079c8bc9566a74d505 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 10 Sep 2021 11:54:26 +0200 Subject: Don't throw when livestream file isn't found --- Emby.Server.Implementations/Library/MediaSourceManager.cs | 8 +++++--- Jellyfin.Api/Controllers/VideosController.cs | 4 ++++ Jellyfin.Api/Helpers/AudioHelper.cs | 7 ++++++- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 8e4b32a9c9..d6d67fcf4b 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -602,7 +602,8 @@ namespace Emby.Server.Implementations.Library public async Task GetLiveStreamMediaInfo(string id, CancellationToken cancellationToken) { - var liveStreamInfo = GetLiveStreamInfo(id); + // TODO probably shouldn't throw here but it is kept for "backwards compatibility" + var liveStreamInfo = GetLiveStreamInfo(id) ?? throw new ResourceNotFoundException(); var mediaSource = liveStreamInfo.MediaSource; @@ -778,7 +779,8 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(id)); } - var info = GetLiveStreamInfo(id); + // TODO probably shouldn't throw here but it is kept for "backwards compatibility" + var info = GetLiveStreamInfo(id) ?? throw new ResourceNotFoundException(); return Task.FromResult(new Tuple(info.MediaSource, info as IDirectStreamProvider)); } @@ -794,7 +796,7 @@ namespace Emby.Server.Implementations.Library return info; } - throw new ResourceNotFoundException(); + return null; } public async Task GetLiveStream(string id, CancellationToken cancellationToken) diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index d7d48ba3e7..e5c27f9e67 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -454,6 +454,10 @@ namespace Jellyfin.Api.Controllers StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); + if (liveStreamInfo == null) + { + return NotFound(); + } var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return File(liveStream, MimeTypes.GetMimeType("file.ts")!); diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 06f889f085..e503551296 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -1,4 +1,5 @@ -using System.Net.Http; +using System.IO; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; @@ -121,6 +122,10 @@ namespace Jellyfin.Api.Helpers StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); + if (liveStreamInfo == null) + { + throw new FileNotFoundException(); + } var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file.ts")); -- cgit v1.2.3 From ff328fefc57461bd999210b3059b997e7f9842ac Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 10 Sep 2021 12:53:45 +0200 Subject: Replace GetDirectStreamProviderByUniqueId with GetLiveStreamInfoByUniqueId --- Emby.Server.Implementations/Library/MediaSourceManager.cs | 13 ++++++------- Jellyfin.Api/Controllers/LiveTvController.cs | 2 +- MediaBrowser.Controller/Library/IMediaSourceManager.cs | 9 +++++++-- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index d6d67fcf4b..16231c73fc 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -587,13 +587,6 @@ namespace Emby.Server.Implementations.Library mediaSource.InferTotalBitrate(); } - public Task GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken) - { - var info = _openStreams.FirstOrDefault(i => i.Value != null && string.Equals(i.Value.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase)); - - return Task.FromResult(info.Value as IDirectStreamProvider); - } - public async Task OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken) { var result = await OpenLiveStreamInternal(request, cancellationToken).ConfigureAwait(false); @@ -799,6 +792,12 @@ namespace Emby.Server.Implementations.Library return null; } + /// + public ILiveStream GetLiveStreamInfoByUniqueId(string uniqueId) + { + return _openStreams.Values.FirstOrDefault(stream => string.Equals(uniqueId, stream?.UniqueId, StringComparison.OrdinalIgnoreCase)); + } + public async Task GetLiveStream(string id, CancellationToken cancellationToken) { var result = await GetLiveStreamWithDirectStreamProvider(id, cancellationToken).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 3f68b267f3..b131530c93 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1201,7 +1201,7 @@ namespace Jellyfin.Api.Controllers [ProducesVideoFile] public ActionResult GetLiveStreamFile([FromRoute, Required] string streamId, [FromRoute, Required] string container) { - var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamId); + var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfoByUniqueId(streamId); if (liveStreamInfo == null) { return NotFound(); diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 0de3ccf3f0..e802796d34 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -116,6 +116,13 @@ namespace MediaBrowser.Controller.Library /// An instance of . public ILiveStream GetLiveStreamInfo(string id); + /// + /// Gets the live stream info using the stream's unique id. + /// + /// The unique identifier. + /// An instance of . + public ILiveStream GetLiveStreamInfoByUniqueId(string uniqueId); + /// /// Closes the media source. /// @@ -132,7 +139,5 @@ namespace MediaBrowser.Controller.Library void SetDefaultAudioAndSubtitleStreamIndexes(BaseItem item, MediaSourceInfo source, User user); Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, string cacheKey, bool addProbeDelay, bool isLiveStream, CancellationToken cancellationToken); - - Task GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken); } } -- cgit v1.2.3 From 2b5f3f294ed7b3660c0a5898d0ece42a7d7cca72 Mon Sep 17 00:00:00 2001 From: ankenyr Date: Sun, 12 Sep 2021 15:05:37 -0700 Subject: Fixing #6269 by comparing PremiereDate when episode comparison would otherwise be equal. --- .../Sorting/AiredEpisodeOrderComparer.cs | 20 +++++++++----------- .../Sorting/AiredEpisodeOrderComparerTests.cs | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 2b0ab536f9..821fa9778a 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -28,16 +28,6 @@ namespace Emby.Server.Implementations.Sorting throw new ArgumentNullException(nameof(y)); } - if (x.PremiereDate.HasValue && y.PremiereDate.HasValue) - { - var val = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); - - if (val != 0) - { - // return val; - } - } - var episode1 = x as Episode; var episode2 = y as Episode; @@ -156,8 +146,16 @@ namespace Emby.Server.Implementations.Sorting { var xValue = ((x.ParentIndexNumber ?? -1) * 1000) + (x.IndexNumber ?? -1); var yValue = ((y.ParentIndexNumber ?? -1) * 1000) + (y.IndexNumber ?? -1); + var compare_val = xValue.CompareTo(yValue); + if (compare_val == 0) + { + if (x.PremiereDate.HasValue & y.PremiereDate.HasValue) + { + compare_val = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); + } + } - return xValue.CompareTo(yValue); + return compare_val; } /// diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs index d9b206f663..e94c509d79 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/AiredEpisodeOrderComparerTests.cs @@ -172,6 +172,25 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 }, 1 }; + // Premiere Date + yield return new object?[] + { + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) }, + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) }, + 0 + }; + yield return new object?[] + { + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 11, 0, 0, 0) }, + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) }, + -1 + }; + yield return new object?[] + { + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) }, + new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 11, 0, 0, 0) }, + 1 + }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); -- cgit v1.2.3 From 83b4d4d25a28b8b83346d78a6c80a877c174c6e1 Mon Sep 17 00:00:00 2001 From: cocool97 Date: Sun, 12 Sep 2021 07:51:23 +0000 Subject: Translated using Weblate (French (Canada)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr_CA/ --- Emby.Server.Implementations/Localization/Core/fr-CA.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json index 3c51d64e04..2a56d07450 100644 --- a/Emby.Server.Implementations/Localization/Core/fr-CA.json +++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json @@ -118,5 +118,7 @@ "TaskCleanActivityLogDescription": "Éfface les entrées du journal plus anciennes que l'âge configuré.", "TaskCleanActivityLog": "Nettoyer le journal d'activité", "Undefined": "Indéfini", - "Forced": "Forcé" + "Forced": "Forcé", + "TaskOptimizeDatabaseDescription": "Compacte la base de données et tronque l'espace libre. Lancer cette tâche après avoir scanné la bibliothèque ou faire d'autres changements impliquant des modifications de la base peuvent ameliorer les performances.", + "TaskOptimizeDatabase": "Optimiser la base de données" } -- cgit v1.2.3 From 65e10946d82873ff00bb405eb56e7204e8e24bdd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:01:22 +0000 Subject: Bump sharpcompress from 0.28.3 to 0.29.0 Bumps [sharpcompress](https://github.com/adamhathcock/sharpcompress) from 0.28.3 to 0.29.0. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.3...0.29) --- updated-dependencies: - dependency-name: sharpcompress dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ad4ad89d1f..e48dbcd191 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,7 +32,7 @@ - + -- cgit v1.2.3 From 96bc24b1dccb7b1f5467659b0350afa74afde243 Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 13 Sep 2021 08:32:12 -0700 Subject: Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs Co-authored-by: Claus Vium --- Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 821fa9778a..12e9c9b784 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -146,12 +146,11 @@ namespace Emby.Server.Implementations.Sorting { var xValue = ((x.ParentIndexNumber ?? -1) * 1000) + (x.IndexNumber ?? -1); var yValue = ((y.ParentIndexNumber ?? -1) * 1000) + (y.IndexNumber ?? -1); - var compare_val = xValue.CompareTo(yValue); - if (compare_val == 0) + var comparisonResult = xValue.CompareTo(yValue); + // If equal, compare premiere dates + if (comparisonResult == 0 && x.PremiereDate.HasValue && y.PremiereDate.HasValue) { - if (x.PremiereDate.HasValue & y.PremiereDate.HasValue) - { - compare_val = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); + comparisonResult = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); } } -- cgit v1.2.3 From 8d45656c51c684fbbf3e94319ac5ec050d5e44b4 Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 13 Sep 2021 08:32:18 -0700 Subject: Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs Co-authored-by: Claus Vium --- Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 12e9c9b784..fd422ffbfc 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.Sorting } } - return compare_val; + return comparisonResult; } /// -- cgit v1.2.3 From d557a5371e63c46c62c62f3c9e0bae1bed0d820c Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 13 Sep 2021 08:32:28 -0700 Subject: Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs Co-authored-by: Claus Vium --- Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index fd422ffbfc..037eb170ac 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -151,7 +151,6 @@ namespace Emby.Server.Implementations.Sorting if (comparisonResult == 0 && x.PremiereDate.HasValue && y.PremiereDate.HasValue) { comparisonResult = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); - } } return comparisonResult; -- cgit v1.2.3 From fffdf9f7b6fe88a0440b5e2eb514987809854667 Mon Sep 17 00:00:00 2001 From: emmanuel billeaud Date: Mon, 13 Sep 2021 11:58:53 +0000 Subject: Translated using Weblate (French) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/ --- Emby.Server.Implementations/Localization/Core/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index 0e4c38425c..c3e52eb81a 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -105,8 +105,8 @@ "TaskRefreshPeople": "Rafraîchir les acteurs", "TaskCleanLogsDescription": "Supprime les journaux de plus de {0} jours.", "TaskCleanLogs": "Nettoyer le répertoire des journaux", - "TaskRefreshLibraryDescription": "Scanne toute les bibliothèques pour trouver les nouveaux fichiers et rafraîchit les métadonnées.", - "TaskRefreshLibrary": "Scanner toutes les Bibliothèques", + "TaskRefreshLibraryDescription": "Scanne votre médiathèque pour trouver les nouveaux fichiers et rafraîchit les métadonnées.", + "TaskRefreshLibrary": "Scanner la médiathèque", "TaskRefreshChapterImagesDescription": "Crée des vignettes pour les vidéos ayant des chapitres.", "TaskRefreshChapterImages": "Extraire les images de chapitre", "TaskCleanCacheDescription": "Supprime les fichiers de cache dont le système n'a plus besoin.", -- cgit v1.2.3 From b9407779e49bf81d31be6be606744259f9e83f40 Mon Sep 17 00:00:00 2001 From: Meem Khan Date: Tue, 14 Sep 2021 20:33:23 +0000 Subject: Translated using Weblate (Urdu (Pakistan)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ur_PK/ --- Emby.Server.Implementations/Localization/Core/ur_PK.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ur_PK.json b/Emby.Server.Implementations/Localization/Core/ur_PK.json index 5d6d0775c4..11af9fc987 100644 --- a/Emby.Server.Implementations/Localization/Core/ur_PK.json +++ b/Emby.Server.Implementations/Localization/Core/ur_PK.json @@ -90,7 +90,7 @@ "NameSeasonUnknown": "نامعلوم باب", "NameSeasonNumber": "باب {0}", "NameInstallFailed": "{0} تنصیب ناکام ہوگئی", - "MusicVideos": "موسیقی ویڈیو", + "MusicVideos": "ویڈیو موسیقی", "Music": "موسیقی", "MixedContent": "مخلوط مواد", "MessageServerConfigurationUpdated": "سرور کو اپ ڈیٹ کر دیا گیا ہے", @@ -99,18 +99,19 @@ "MessageApplicationUpdated": "جیلیفن سرور کو اپ ڈیٹ کر دیا گیا ہے", "Latest": "تازہ ترین", "LabelRunningTimeValue": "چلانے کی مدت", - "LabelIpAddressValue": "ای پی پتے {0}", + "LabelIpAddressValue": "آئ پی ایڈریس {0}", "ItemRemovedWithName": "لائبریری سے ہٹا دیا گیا ھے", "ItemAddedWithName": "[0} لائبریری میں شامل کیا گیا ھے", "Inherit": "وراثت میں", "HomeVideos": "ہوم ویڈیو", "HeaderRecordingGroups": "ریکارڈنگ گروپس", - "FailedLoginAttemptWithUserName": "لاگن کئ کوشش ناکام {0}", + "FailedLoginAttemptWithUserName": "{0} سے لاگ ان کی ناکام کوشش", "DeviceOnlineWithName": "{0} متصل ھو چکا ھے", "DeviceOfflineWithName": "{0} منقطع ھو چکا ھے", "ChapterNameValue": "باب", "AuthenticationSucceededWithUserName": "{0} کامیابی کے ساتھ تصدیق ھوچکی ھے", "CameraImageUploadedFrom": "ایک نئی کیمرہ تصویر اپ لوڈ کی گئی ہے {0}", "Application": "پروگرام", - "AppDeviceValues": "پروگرام:{0}, آلہ:{1}" + "AppDeviceValues": "پروگرام:{0}, ڈیوائس:{1}", + "Forced": "جَبری" } -- cgit v1.2.3 From 8d57afb55f5258f67bcda5c6e49ecc8d8e62a60a Mon Sep 17 00:00:00 2001 From: gbrea Date: Thu, 16 Sep 2021 06:49:00 +0000 Subject: Translated using Weblate (Galician) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gl/ --- Emby.Server.Implementations/Localization/Core/gl.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json index afb22ab472..b433c6f68c 100644 --- a/Emby.Server.Implementations/Localization/Core/gl.json +++ b/Emby.Server.Implementations/Localization/Core/gl.json @@ -48,7 +48,7 @@ "HeaderFavoriteArtists": "Artistas Favoritos", "HeaderFavoriteAlbums": "Álbunes Favoritos", "HeaderContinueWatching": "Seguir mirando", - "HeaderAlbumArtists": "Artistas de Album", + "HeaderAlbumArtists": "Artistas do Album", "Genres": "Xéneros", "Forced": "Forzado", "Folders": "Cartafoles", @@ -117,5 +117,7 @@ "UserPolicyUpdatedWithName": "A política de usuario foi actualizada para {0}", "UserPasswordChangedWithName": "Cambiouse o contrasinal para o usuario {0}", "UserOnlineFromDevice": "{0} está en liña desde {1}", - "UserOfflineFromDevice": "{0} desconectouse desde {1}" + "UserOfflineFromDevice": "{0} desconectouse desde {1}", + "TaskOptimizeDatabaseDescription": "Compacta e libera o espazo libre da base de datos. Executar esta tarefa logo de realizar mudanzas que impliquen modificacións da base de datos ou despois de escanear a biblioteca pode traer mellorías de desempeño.", + "TaskOptimizeDatabase": "Optimizar base de datos" } -- cgit v1.2.3 From a6d1e542e62548f177523f0acd67260f58066731 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 19 Sep 2021 20:53:31 +0200 Subject: Reduce allocations --- Emby.Dlna/Eventing/DlnaEventManager.cs | 5 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 7 +-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 59 ++++++++++------------ .../LiveTv/TunerHosts/M3uParser.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 3 +- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 4 +- .../Parsers/BaseItemXmlParser.cs | 3 +- .../Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs | 4 +- MediaBrowser.Model/Net/MimeTypes.cs | 3 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 3 +- src/Jellyfin.Extensions/StringExtensions.cs | 34 +++++++++++++ .../StringExtensionsTests.cs | 21 ++++++++ 14 files changed, 105 insertions(+), 48 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index 3c91360904..b39bd5ce9b 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -11,6 +11,7 @@ using System.Net.Http; using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using Microsoft.Extensions.Logging; @@ -82,9 +83,7 @@ namespace Emby.Dlna.Eventing if (!string.IsNullOrEmpty(header)) { // Starts with SECOND- - header = header.Split('-')[^1]; - - if (int.TryParse(header, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, _usCulture, out var val)) { return val; } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 8202fab861..cb9801c178 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using Jellyfin.XmlTv; using Jellyfin.XmlTv.Entities; using MediaBrowser.Common.Extensions; @@ -89,11 +90,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings return UnzipIfNeeded(path, cacheFile); } - private string UnzipIfNeeded(string originalUrl, string file) + private string UnzipIfNeeded(ReadOnlySpan originalUrl, string file) { - string ext = Path.GetExtension(originalUrl.Split('?')[0]); + ReadOnlySpan ext = Path.GetExtension(originalUrl.LeftPart('?')); - if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".gz", StringComparison.OrdinalIgnoreCase)) { try { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2bd12a9c8f..4d538c6043 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -36,7 +36,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; - private readonly INetworkManager _networkManager; private readonly IStreamHelper _streamHelper; private readonly JsonSerializerOptions _jsonOptions; @@ -50,7 +49,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, ISocketFactory socketFactory, - INetworkManager networkManager, IStreamHelper streamHelper, IMemoryCache memoryCache) : base(config, logger, fileSystem, memoryCache) @@ -58,7 +56,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _httpClientFactory = httpClientFactory; _appHost = appHost; _socketFactory = socketFactory; - _networkManager = networkManager; _streamHelper = streamHelper; _jsonOptions = JsonDefaults.Options; @@ -70,7 +67,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun protected override string ChannelIdPrefix => "hdhr_"; - private string GetChannelId(TunerHostInfo info, Channels i) + private string GetChannelId(Channels i) => ChannelIdPrefix + i.GuideNumber; internal async Task> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) @@ -103,7 +100,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { Name = i.GuideName, Number = i.GuideNumber, - Id = GetChannelId(tuner, i), + Id = GetChannelId(i), IsFavorite = i.Favorite, TunerHostId = tuner.Id, IsHD = i.HD, @@ -255,7 +252,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - var tuners = new List(); + var tuners = new List(model.TunerCount); var uri = new Uri(GetApiUrl(info)); @@ -264,10 +261,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Legacy HdHomeruns are IPv4 only var ipInfo = IPAddress.Parse(uri.Host); - for (int i = 0; i < model.TunerCount; ++i) + for (int i = 0; i < model.TunerCount; i++) { var name = string.Format(CultureInfo.InvariantCulture, "Tuner {0}", i + 1); - var currentChannel = "none"; // @todo Get current channel and map back to Station Id + var currentChannel = "none"; // TODO: Get current channel and map back to Station Id var isAvailable = await manager.CheckTunerAvailability(ipInfo, i, cancellationToken).ConfigureAwait(false); var status = isAvailable ? LiveTvTunerStatus.Available : LiveTvTunerStatus.LiveTv; tuners.Add(new LiveTvTunerInfo @@ -455,28 +452,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Path = url, Protocol = MediaProtocol.Udp, MediaStreams = new List - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = isInterlaced, - Codec = videoCodec, - Width = width, - Height = height, - BitRate = videoBitrate, - NalLengthSize = nal - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1, - Codec = audioCodec, - BitRate = audioBitrate - } - }, + { + new MediaStream + { + Type = MediaStreamType.Video, + // Set the index to -1 because we don't know the exact index of the video stream within the container + Index = -1, + IsInterlaced = isInterlaced, + Codec = videoCodec, + Width = width, + Height = height, + BitRate = videoBitrate, + NalLengthSize = nal + }, + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1, + Codec = audioCodec, + BitRate = audioBitrate + } + }, RequiresOpening = true, RequiresClosing = true, BufferMs = 0, @@ -551,7 +548,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - var profile = streamId.Split('_')[0]; + var profile = streamId.AsSpan().LeftPart('_').ToString(); Logger.LogInformation("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channel.Id, streamId, profile); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 23071a4306..506ef5548a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/')[^1]); + numberString = Path.GetFileNameWithoutExtension(mediaUrl.AsSpan().RightPart('/')).ToString(); if (!IsValidChannelNumber(numberString)) { diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 7a2c23991b..bcb2b50c7a 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -7,6 +7,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -199,7 +200,7 @@ namespace Jellyfin.Api.Controllers throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType)); } - var ext = response.Content.Headers.ContentType.MediaType.Split('/')[^1]; + var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 0041251e3d..4fc791665e 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; @@ -81,7 +82,7 @@ namespace Jellyfin.Api.Helpers throw new ResourceNotFoundException(nameof(httpRequest.Path)); } - var url = httpRequest.Path.Value.Split('.')[^1]; + var url = httpRequest.Path.Value.AsSpan().RightPart('.').ToString(); if (string.IsNullOrEmpty(streamingRequest.AudioCodec)) { diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index aa5e2c4038..c4ddc5618d 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -120,7 +120,7 @@ namespace MediaBrowser.Controller.MediaEncoding var size = part.Split('=', 2)[^1]; int? scale = null; - if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) + if (size.Contains("kb", StringComparison.OrdinalIgnoreCase)) { scale = 1024; size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); @@ -139,7 +139,7 @@ namespace MediaBrowser.Controller.MediaEncoding var rate = part.Split('=', 2)[^1]; int? scale = null; - if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) + if (rate.Contains("kbits/s", StringComparison.OrdinalIgnoreCase)) { scale = 1024; rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index ef130ee747..9103bf6476 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -331,7 +332,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, _usCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 2516aad1cc..c377f1720d 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1378,7 +1378,7 @@ namespace MediaBrowser.MediaEncoding.Probing { var disc = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.Split('/')[0], out var discNum)) + if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.AsSpan().LeftPart('/'), out var discNum)) { return discNum; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs index ad32cb7943..6d56dda91f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs @@ -18,14 +18,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { writer.WriteLine("WEBVTT"); - writer.WriteLine(string.Empty); + writer.WriteLine(); writer.WriteLine("REGION"); writer.WriteLine("id:subtitle"); writer.WriteLine("width:80%"); writer.WriteLine("lines:3"); writer.WriteLine("regionanchor:50%,100%"); writer.WriteLine("viewportanchor:50%,90%"); - writer.WriteLine(string.Empty); + writer.WriteLine(); foreach (var trackEvent in info.TrackEvents) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 96f5ab51ae..7b3c17c85a 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Net { @@ -221,7 +222,7 @@ namespace MediaBrowser.Model.Net } // handle text/html; charset=UTF-8 - mimeType = mimeType.Split(';')[0]; + mimeType = mimeType.AsSpan().LeftPart(';').ToString(); if (_extensionLookup.TryGetValue(mimeType, out string? result)) { diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index f975278fbc..b3efb8634f 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Providers; using MediaBrowser.Controller.Entities; @@ -474,7 +475,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, UsCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, UsCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index acc695ed2f..3a77072539 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -27,5 +27,39 @@ namespace Jellyfin.Extensions return count; } + + /// + /// Returns the part on the left of the needle. + /// + /// The string to seek. + /// The needle to find. + /// The part left of the . + public static ReadOnlySpan LeftPart(this ReadOnlySpan haystack, char needle) + { + var pos = haystack.IndexOf(needle); + return pos == -1 ? haystack : haystack[..pos]; + } + + /// + /// Returns the part on the right of the needle. + /// + /// The string to seek. + /// The needle to find. + /// The part right of the . + public static ReadOnlySpan RightPart(this ReadOnlySpan haystack, char needle) + { + var pos = haystack.LastIndexOf(needle); + if (pos == -1) + { + return haystack; + } + + if (pos == haystack.Length - 1) + { + return ReadOnlySpan.Empty; + } + + return haystack[(pos + 1)..]; + } } } diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs index d1aa2e4764..17671d13b0 100644 --- a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs @@ -14,5 +14,26 @@ namespace Jellyfin.Extensions.Tests { Assert.Equal(count, str.AsSpan().Count(needle)); } + + [Theory] + [InlineData("", 'q', "")] + [InlineData("Banana split", ' ', "Banana")] + [InlineData("Banana split", 'q', "Banana split")] + public void LeftPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult) + { + var result = str.AsSpan().LeftPart(needle).ToString(); + Assert.Equal(expectedResult, result); + } + + [Theory] + [InlineData("", 'q', "")] + [InlineData("Banana split", ' ', "split")] + [InlineData("Banana split", 'q', "Banana split")] + [InlineData("Banana split.", '.', "")] + public void RightPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult) + { + var result = str.AsSpan().RightPart(needle).ToString(); + Assert.Equal(expectedResult, result); + } } } -- cgit v1.2.3 From e7d6c4550989e960bba8f94f68da1cbc1b7b2006 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sun, 19 Sep 2021 15:06:27 -0600 Subject: Upgrade to dotnet 5.0.10 --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++-- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index e48dbcd191..fda008397c 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -29,7 +29,7 @@ - + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 2fca88f24e..7f4eb0378a 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,7 +14,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index a75b285936..434c414a4a 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 1fdad73b74..fc935cecb2 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -33,8 +33,8 @@ - - + + diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index d88efcdc95..6b18e75836 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -19,7 +19,7 @@ RUN apt-get update -yqq \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/13b9d84c-a35b-4ffe-8f62-447a01403d64/1f9ae31daa0f7d98513e7551246899f2/dotnet-sdk-5.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 4f41bba2d9..50b116a677 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -18,7 +18,7 @@ RUN apt-get update -yqq \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/13b9d84c-a35b-4ffe-8f62-447a01403d64/1f9ae31daa0f7d98513e7551246899f2/dotnet-sdk-5.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 01752d5367..1b1e252f78 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -18,7 +18,7 @@ RUN apt-get update -yqq \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/13b9d84c-a35b-4ffe-8f62-447a01403d64/1f9ae31daa0f7d98513e7551246899f2/dotnet-sdk-5.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5972698f-ba44-4664-9c50-bdc69ca70fb7/1cf7d94425d8dd4d5789dfa978d61475/dotnet-sdk-5.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 0c36e81cca..9dac63e703 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 592b444c99..42e60df5fb 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index f249be674c..4f0bbc36cf 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,7 +10,7 @@ - + -- cgit v1.2.3 From dc8420c7a20f462bdd3b02d7f20743c3ada66ecb Mon Sep 17 00:00:00 2001 From: Dixin Date: Sun, 19 Sep 2021 16:54:00 -0700 Subject: Fix extra folder type resolving. --- .../Library/CoreResolutionIgnoreRule.cs | 4 +- .../Library/LibraryManager.cs | 4 +- .../Library/Resolvers/TV/EpisodeResolver.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 78 +++++++++------------- 4 files changed, 35 insertions(+), 53 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index c7d1139639..bc5b4499fc 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.Library if (parent != null) { // Ignore trailer folders but allow it at the collection level - if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) + if (string.Equals(filename, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase) && !(parent is AggregateFolder) && !(parent is UserRootFolder)) { @@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.Library if (parent != null) { // Don't resolve these into audio files - if (Path.GetFileNameWithoutExtension(filename.AsSpan()).Equals(BaseItem.ThemeSongFilename, StringComparison.Ordinal) + if (Path.GetFileNameWithoutExtension(filename.AsSpan()).Equals(BaseItem.ThemeSongFileName, StringComparison.Ordinal) && _libraryManager.IsAudioFile(filename)) { return true; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 8054beae3f..6f0f3d080d 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2714,7 +2714,7 @@ namespace Emby.Server.Implementations.Library var namingOptions = GetNamingOptions(); var files = owner.IsInMixedFolder ? new List() : fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase)) + .Where(i => string.Equals(i.Name, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase)) .SelectMany(i => _fileSystem.GetFiles(i.FullName, _videoFileExtensions, false, false)) .ToList(); @@ -2758,7 +2758,7 @@ namespace Emby.Server.Implementations.Library var namingOptions = GetNamingOptions(); var files = owner.IsInMixedFolder ? new List() : fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => BaseItem.AllExtrasTypesFolderNames.Contains(i.Name ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + .Where(i => BaseItem.AllExtrasTypesFolderNames.ContainsKey(i.Name ?? string.Empty)) .SelectMany(i => _fileSystem.GetFiles(i.FullName, _videoFileExtensions, false, false)) .ToList(); diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index d6ae910565..cf2d22f4df 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if ((season != null || string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || args.HasParent()) - && (parent is Series || !BaseItem.AllExtrasTypesFolderNames.Contains(parent.Name, StringComparer.OrdinalIgnoreCase))) + && (parent is Series || !BaseItem.AllExtrasTypesFolderNames.ContainsKey(parent.Name))) { var episode = ResolveVideo(args, false); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f4c91973bd..1996ab618e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -44,18 +44,10 @@ namespace MediaBrowser.Controller.Entities /// /// The trailer folder name. /// - public const string TrailerFolderName = "trailers"; + public const string TrailersFolderName = "trailers"; public const string ThemeSongsFolderName = "theme-music"; - public const string ThemeSongFilename = "theme"; + public const string ThemeSongFileName = "theme"; public const string ThemeVideosFolderName = "backdrops"; - public const string ExtrasFolderName = "extras"; - public const string BehindTheScenesFolderName = "behind the scenes"; - public const string DeletedScenesFolderName = "deleted scenes"; - public const string InterviewFolderName = "interviews"; - public const string SceneFolderName = "scenes"; - public const string SampleFolderName = "samples"; - public const string ShortsFolderName = "shorts"; - public const string FeaturettesFolderName = "featurettes"; /// /// The supported image extensions. @@ -93,16 +85,20 @@ namespace MediaBrowser.Controller.Entities }; public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; - public static readonly string[] AllExtrasTypesFolderNames = - { - ExtrasFolderName, - BehindTheScenesFolderName, - DeletedScenesFolderName, - InterviewFolderName, - SceneFolderName, - SampleFolderName, - ShortsFolderName, - FeaturettesFolderName + + /// + /// The supported extra folder names and types. See . + /// + public static readonly Dictionary AllExtrasTypesFolderNames = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + ["extras"] = MediaBrowser.Model.Entities.ExtraType.Unknown, + ["behind the scenes"] = MediaBrowser.Model.Entities.ExtraType.BehindTheScenes, + ["deleted scenes"] = MediaBrowser.Model.Entities.ExtraType.DeletedScene, + ["interviews"] = MediaBrowser.Model.Entities.ExtraType.Interview, + ["scenes"] = MediaBrowser.Model.Entities.ExtraType.Scene, + ["samples"] = MediaBrowser.Model.Entities.ExtraType.Sample, + ["shorts"] = MediaBrowser.Model.Entities.ExtraType.Clip, + ["featurettes"] = MediaBrowser.Model.Entities.ExtraType.Clip }; private string _sortName; @@ -1358,7 +1354,7 @@ namespace MediaBrowser.Controller.Entities // Support plex/xbmc convention files.AddRange(fileSystemChildren - .Where(i => !i.IsDirectory && System.IO.Path.GetFileNameWithoutExtension(i.FullName.AsSpan()).Equals(ThemeSongFilename, StringComparison.OrdinalIgnoreCase))); + .Where(i => !i.IsDirectory && System.IO.Path.GetFileNameWithoutExtension(i.FullName.AsSpan()).Equals(ThemeSongFileName, StringComparison.OrdinalIgnoreCase))); return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) .OfType() @@ -1417,39 +1413,25 @@ namespace MediaBrowser.Controller.Entities protected virtual BaseItem[] LoadExtras(List fileSystemChildren, IDirectoryService directoryService) { - var extras = new List /// The filename. /// DlnaIconResponse. - ImageStream GetIcon(string filename); + ImageStream? GetIcon(string filename); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index c7f61a90bb..7ca0e851bd 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Drawing /// Guid. string GetImageCacheTag(BaseItem item, ItemImageInfo image); - string GetImageCacheTag(BaseItem item, ChapterInfo info); + string GetImageCacheTag(BaseItem item, ChapterInfo chapter); string? GetImageCacheTag(User user); diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 0f697bcccd..47cec7d77f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -32,7 +32,7 @@ - net5.0 + net6.0 false true true diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index b09b7dba6c..e92c4a08a6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -541,7 +541,12 @@ namespace MediaBrowser.Controller.MediaEncoding return MimeType; } - return MimeTypes.GetMimeType(outputPath, enableStreamDefault); + if (enableStreamDefault) + { + return MimeTypes.GetMimeType(outputPath); + } + + return MimeTypes.GetMimeType(outputPath, null); } public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced) diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 1cf8fcd1b5..a3db717b9f 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -11,7 +11,7 @@ - net5.0 + net6.0 false true diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 5deaecc952..30cfb904e1 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false true diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 3d864e29ca..20e4be7802 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subRip.LoadSubtitle(subtitle, lines, "untitled"); if (subRip.ErrorCount > 0) { - _logger.LogError("{ErrorCount} errors encountered while parsing subtitle."); + _logger.LogError("{ErrorCount} errors encountered while parsing subtitle.", subRip.ErrorCount); } var trackInfo = new SubtitleTrackInfo(); diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index a371afc2cf..b0a12a9c90 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,7 +14,7 @@ - net5.0 + net6.0 false true true diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 7b3c17c85a..1d9150f02b 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Jellyfin.Extensions; @@ -164,15 +165,16 @@ namespace MediaBrowser.Model.Net return dict; } - public static string? GetMimeType(string path) => GetMimeType(path, true); + public static string GetMimeType(string path) => GetMimeType(path, "application/octet-stream"); /// /// Gets the type of the MIME. /// /// The filename to find the MIME type of. - /// Whether of not to return a default value if no fitting MIME type is found. - /// The worrect MIME type for the given filename, or `null` if it wasn't found and is false. - public static string? GetMimeType(string filename, bool enableStreamDefault) + /// Theefault value to return if no fitting MIME type is found. + /// The correct MIME type for the given filename, or if it wasn't found. + [return: NotNullIfNotNullAttribute("defaultValue")] + public static string? GetMimeType(string filename, string? defaultValue = null) { if (filename.Length == 0) { @@ -211,7 +213,7 @@ namespace MediaBrowser.Model.Net return "application/octet-stream"; } - return enableStreamDefault ? "application/octet-stream" : null; + return defaultValue; } public static string? ToExtension(string mimeType) diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3a6e162746..29d6b01f23 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -26,7 +26,7 @@ - net5.0 + net6.0 false true ../jellyfin.ruleset diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs index 268538815e..19d90b9a1b 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (reader.TokenType == JsonTokenType.String) { var str = reader.GetString(); - if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + if (str == null || str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) { return null; } diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 3e2a9bacf1..926be5a927 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,7 +15,7 @@ - net5.0 + net6.0 false true diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 7d6a471f95..5d7da4124e 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text; namespace Rssdp.Infrastructure @@ -45,11 +46,11 @@ namespace Rssdp.Infrastructure const string ArgFormat = "{0}: {1}\r\n"; - builder.AppendFormat("{0}\r\n", header); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}\r\n", header); foreach (var pair in values) { - builder.AppendFormat(ArgFormat, pair.Key, pair.Value); + builder.AppendFormat(CultureInfo.InvariantCulture, ArgFormat, pair.Key, pair.Value); } builder.Append("\r\n"); diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 54113d4644..77130983b5 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -11,7 +11,7 @@ - net5.0 + net6.0 false AllDisabledByDefault disable diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 4005d836d9..c826830f1d 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; using Rssdp.Infrastructure; namespace Rssdp @@ -134,11 +135,13 @@ namespace Rssdp { get { - return String.Format("urn:{0}:{3}:{1}:{2}", - this.DeviceTypeNamespace ?? String.Empty, - this.DeviceType ?? String.Empty, - this.DeviceVersion, - this.DeviceClass ?? "device"); + return String.Format( + CultureInfo.InvariantCulture, + "urn:{0}:{3}:{1}:{2}", + this.DeviceTypeNamespace ?? String.Empty, + this.DeviceType ?? String.Empty, + this.DeviceVersion, + this.DeviceClass ?? "device"); } } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index c9e795d565..64d19803df 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; using System.Linq; using System.Net; using System.Threading; @@ -233,7 +234,7 @@ namespace Rssdp.Infrastructure { if (String.IsNullOrEmpty(searchTarget)) { - WriteTrace(String.Format("Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString())); + WriteTrace(String.Format(CultureInfo.InvariantCulture, "Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString())); return; } @@ -340,7 +341,7 @@ namespace Rssdp.Infrastructure private string GetUsn(string udn, string fullDeviceType) { - return String.Format("{0}::{1}", udn, fullDeviceType); + return String.Format(CultureInfo.InvariantCulture, "{0}::{1}", udn, fullDeviceType); } private async void SendSearchResponse( @@ -363,7 +364,7 @@ namespace Rssdp.Infrastructure values["DATE"] = DateTime.UtcNow.ToString("r"); values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds; values["ST"] = searchTarget; - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["USN"] = uniqueServiceName; values["LOCATION"] = rootDevice.Location.ToString(); @@ -497,7 +498,7 @@ namespace Rssdp.Infrastructure values["DATE"] = DateTime.UtcNow.ToString("r"); values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds; values["LOCATION"] = rootDevice.Location.ToString(); - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["NTS"] = "ssdp:alive"; values["NT"] = notificationType; values["USN"] = uniqueServiceName; @@ -522,7 +523,7 @@ namespace Rssdp.Infrastructure } tasks.Add(SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken)); - tasks.Add(SendByeByeNotification(device, String.Format("urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken)); + tasks.Add(SendByeByeNotification(device, String.Format(CultureInfo.InvariantCulture, "urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken)); foreach (var childDevice in device.Devices) { @@ -542,7 +543,7 @@ namespace Rssdp.Infrastructure // If needed later for non-server devices, these headers will need to be dynamic values["HOST"] = "239.255.255.250:1900"; values["DATE"] = DateTime.UtcNow.ToString("r"); - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["NTS"] = "ssdp:byebye"; values["NT"] = notificationType; values["USN"] = uniqueServiceName; @@ -550,7 +551,7 @@ namespace Rssdp.Infrastructure var message = BuildMessage(header, values); var sendCount = IsDisposed ? 1 : 3; - WriteTrace(String.Format("Sent byebye notification"), device); + WriteTrace(String.Format(CultureInfo.InvariantCulture, "Sent byebye notification"), device); return _CommsServer.SendMulticastMessage(message, sendCount, _sendOnlyMatchedHost ? device.ToRootDevice().Address : null, cancellationToken); } diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 9dac63e703..b52ea078af 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 1619fa89c8..1fe4e25656 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index a5778b59c8..e9a9515710 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 5a48631c29..1fb95aab4d 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index 20680157f5..2dc4ac19a5 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e9cd8c0623..201f63a2d6 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 09b8a7a948..a37e5ac920 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index a4ebab141e..75d466198a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 5fa2ecfe9e..75d9b9ea90 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 9b6ab7bdf5..5ecd846047 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -6,7 +6,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset Jellyfin.Server.Implementations.Tests diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 42e60df5fb..7939c7118e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -1,6 +1,6 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 4f0bbc36cf..b30e690a5e 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index e085907583..94294c8bf3 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset -- cgit v1.2.3 From 4d1d9f23d5edd248900118963874a7ab83d04aa1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 23 May 2021 00:20:19 +0200 Subject: Use new Enum.TryParse(ReadOnlySpan) overload --- Emby.Dlna/DlnaManager.cs | 10 +++++--- .../Data/SqliteItemRepository.cs | 27 +++++++++------------- .../Library/LibraryManager.cs | 4 +--- MediaBrowser.Controller/Drawing/ImageStream.cs | 9 ++++++-- .../Jellyfin.Providers.Tests.csproj | 2 +- 5 files changed, 27 insertions(+), 25 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 3855504324..305e43a3ca 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -493,11 +493,15 @@ namespace Emby.Dlna : ImageFormat.Jpg; var resource = GetType().Namespace + ".Images." + filename.ToLowerInvariant(); + var stream = _assembly.GetManifestResourceStream(resource); + if (stream == null) + { + return null; + } - return new ImageStream + return new ImageStream(stream) { - Format = format, - Stream = _assembly.GetManifestResourceStream(resource) + Format = format }; } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 88fc5018df..88cd4476a7 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1150,7 +1150,7 @@ namespace Emby.Server.Implementations.Data return null; } - if (Enum.TryParse(imageType.ToString(), true, out ImageType type)) + if (Enum.TryParse(imageType, true, out ImageType type)) { image.Type = type; } @@ -1571,7 +1571,6 @@ namespace Emby.Server.Implementations.Data if (reader.TryGetString(index++, out var audioString)) { - // TODO Span overload coming in the future https://github.com/dotnet/runtime/issues/1916 if (Enum.TryParse(audioString, true, out ProgramAudio audio)) { item.Audio = audio; @@ -1610,18 +1609,16 @@ namespace Emby.Server.Implementations.Data { if (reader.TryGetString(index++, out var lockedFields)) { - IEnumerable GetLockedFields(string s) + List fields = null; + foreach (var i in lockedFields.Split('|')) { - foreach (var i in s.Split('|', StringSplitOptions.RemoveEmptyEntries)) + if (Enum.TryParse(i, true, out MetadataField parsedValue)) { - if (Enum.TryParse(i, true, out MetadataField parsedValue)) - { - yield return parsedValue; - } + (fields ??= new List()).Add(parsedValue); } } - item.LockedFields = GetLockedFields(lockedFields).ToArray(); + item.LockedFields = fields?.ToArray() ?? Array.Empty(); } } @@ -1647,18 +1644,16 @@ namespace Emby.Server.Implementations.Data { if (reader.TryGetString(index, out var trailerTypes)) { - IEnumerable GetTrailerTypes(string s) + List types = null; + foreach (var i in trailerTypes.Split('|')) { - foreach (var i in s.Split('|', StringSplitOptions.RemoveEmptyEntries)) + if (Enum.TryParse(i, true, out TrailerType parsedValue)) { - if (Enum.TryParse(i, true, out TrailerType parsedValue)) - { - yield return parsedValue; - } + (types ??= new List()).Add(parsedValue); } } - trailer.TrailerTypes = GetTrailerTypes(trailerTypes).ToArray(); + trailer.TrailerTypes = types.ToArray() ?? Array.Empty(); } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 6f0f3d080d..132486b4a6 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1250,10 +1250,8 @@ namespace Emby.Server.Implementations.Library private CollectionTypeOptions? GetCollectionType(string path) { var files = _fileSystem.GetFilePaths(path, new[] { ".collection" }, true, false); - foreach (var file in files) + foreach (ReadOnlySpan file in files) { - // TODO: @bond use a ReadOnlySpan here when Enum.TryParse supports it - // https://github.com/dotnet/runtime/issues/20008 if (Enum.TryParse(Path.GetFileNameWithoutExtension(file), true, out var res)) { return res; diff --git a/MediaBrowser.Controller/Drawing/ImageStream.cs b/MediaBrowser.Controller/Drawing/ImageStream.cs index 5d552170f9..f4c3057993 100644 --- a/MediaBrowser.Controller/Drawing/ImageStream.cs +++ b/MediaBrowser.Controller/Drawing/ImageStream.cs @@ -8,11 +8,16 @@ namespace MediaBrowser.Controller.Drawing { public class ImageStream : IDisposable { + public ImageStream(Stream stream) + { + Stream = stream; + } + /// - /// Gets or sets the stream. + /// Gets the stream. /// /// The stream. - public Stream? Stream { get; set; } + public Stream Stream { get; } /// /// Gets or sets the format. diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index d9e33617bc..0b2db64b0b 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false ../jellyfin-tests.ruleset -- cgit v1.2.3 From fb2f07dc84bfd75e72aaaa8d595c3267a52678de Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 21 Sep 2021 23:24:43 +0200 Subject: Replace RNGCryptoServiceProvider with RandomNumberGenerator --- .../QuickConnect/QuickConnectManager.cs | 28 +++------------------- 1 file changed, 3 insertions(+), 25 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index ae773c6589..c81c269945 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.QuickConnect /// /// Quick connect implementation. /// - public class QuickConnectManager : IQuickConnect, IDisposable + public class QuickConnectManager : IQuickConnect { /// /// The length of user facing codes. @@ -30,7 +30,6 @@ namespace Emby.Server.Implementations.QuickConnect /// private const int Timeout = 10; - private readonly RNGCryptoServiceProvider _rng = new (); private readonly ConcurrentDictionary _currentRequests = new (); private readonly ConcurrentDictionary _authorizedSecrets = new (); @@ -140,7 +139,7 @@ namespace Emby.Server.Implementations.QuickConnect uint scale = uint.MaxValue; while (scale == uint.MaxValue) { - _rng.GetBytes(raw); + RandomNumberGenerator.Fill(raw); scale = BitConverter.ToUInt32(raw); } @@ -199,31 +198,10 @@ namespace Emby.Server.Implementations.QuickConnect return result.AuthenticationResult; } - /// - /// Dispose. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Dispose. - /// - /// Dispose unmanaged resources. - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _rng.Dispose(); - } - } - private string GenerateSecureRandom(int length = 32) { Span bytes = stackalloc byte[length]; - _rng.GetBytes(bytes); + RandomNumberGenerator.Fill(bytes); return Convert.ToHexString(bytes); } -- cgit v1.2.3 From 5fd315b17c7c95c05eaba0713b27f6a95d31e164 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 24 Sep 2021 20:15:10 +0200 Subject: Address comments --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 6 +++--- MediaBrowser.Model/Net/MimeTypes.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 88cd4476a7..0a48b844dd 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1610,7 +1610,7 @@ namespace Emby.Server.Implementations.Data if (reader.TryGetString(index++, out var lockedFields)) { List fields = null; - foreach (var i in lockedFields.Split('|')) + foreach (var i in lockedFields.AsSpan().Split('|')) { if (Enum.TryParse(i, true, out MetadataField parsedValue)) { @@ -1645,7 +1645,7 @@ namespace Emby.Server.Implementations.Data if (reader.TryGetString(index, out var trailerTypes)) { List types = null; - foreach (var i in trailerTypes.Split('|')) + foreach (var i in trailerTypes.AsSpan().Split('|')) { if (Enum.TryParse(i, true, out TrailerType parsedValue)) { @@ -1653,7 +1653,7 @@ namespace Emby.Server.Implementations.Data } } - trailer.TrailerTypes = types.ToArray() ?? Array.Empty(); + trailer.TrailerTypes = types?.ToArray() ?? Array.Empty(); } } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 1d9150f02b..748170a0e1 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Model.Net /// Gets the type of the MIME. /// /// The filename to find the MIME type of. - /// Theefault value to return if no fitting MIME type is found. + /// The default value to return if no fitting MIME type is found. /// The correct MIME type for the given filename, or if it wasn't found. [return: NotNullIfNotNullAttribute("defaultValue")] public static string? GetMimeType(string filename, string? defaultValue = null) -- cgit v1.2.3 From 984f17c64f0dac54d926124ae77866e1781799ba Mon Sep 17 00:00:00 2001 From: Ouail Ouazani Date: Fri, 24 Sep 2021 13:11:19 +0000 Subject: Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index be629c8a42..5a4a4d5a91 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -1,5 +1,5 @@ { - "Albums": "البومات", + "Albums": "ألبومات", "AppDeviceValues": "تطبيق: {0}, جهاز: {1}", "Application": "تطبيق", "Artists": "الفنانين", @@ -8,7 +8,7 @@ "CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}", "Channels": "القنوات", "ChapterNameValue": "الفصل {0}", - "Collections": "مجموعات", + "Collections": "التجميعات", "DeviceOfflineWithName": "قُطِع الاتصال ب{0}", "DeviceOnlineWithName": "{0} متصل", "FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}", -- cgit v1.2.3 From d81c9a7a8cbab8967bfc66086c6f0f80bf7fc0c2 Mon Sep 17 00:00:00 2001 From: Mislav Milinković Date: Fri, 24 Sep 2021 11:31:45 +0000 Subject: Translated using Weblate (Croatian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hr/ --- Emby.Server.Implementations/Localization/Core/hr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/hr.json b/Emby.Server.Implementations/Localization/Core/hr.json index 9eb80b83ba..d7cda61da6 100644 --- a/Emby.Server.Implementations/Localization/Core/hr.json +++ b/Emby.Server.Implementations/Localization/Core/hr.json @@ -15,7 +15,7 @@ "Favorites": "Favoriti", "Folders": "Mape", "Genres": "Žanrovi", - "HeaderAlbumArtists": "Izvođači na albumu", + "HeaderAlbumArtists": "Album od izvođača", "HeaderContinueWatching": "Nastavi gledati", "HeaderFavoriteAlbums": "Omiljeni albumi", "HeaderFavoriteArtists": "Omiljeni izvođači", -- cgit v1.2.3 From f31224fa8f1dccb730703c048c26e14b5d14fa55 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 25 Sep 2021 19:44:40 +0200 Subject: Remove sync FileStream hack --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 2 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 4 ++-- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 +- .../LiveTv/TunerHosts/LiveStream.cs | 6 +++--- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 2 +- Jellyfin.Api/Controllers/SystemController.cs | 2 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 2 +- Jellyfin.Api/Helpers/ProgressiveFileStream.cs | 24 ++-------------------- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../SymlinkFollowingPhysicalFileResultExecutor.cs | 2 +- Jellyfin.Server/Program.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/IO/AsyncFile.cs | 11 ++-------- MediaBrowser.Providers/Manager/ImageSaver.cs | 2 +- .../Manager/ItemImageProvider.cs | 2 +- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 2 +- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 4 ++-- .../Studios/StudiosImageProvider.cs | 2 +- .../Subtitles/SubtitleManager.cs | 2 +- 23 files changed, 29 insertions(+), 56 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 305e43a3ca..8fe9d484e7 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -366,7 +366,7 @@ namespace Emby.Dlna Directory.CreateDirectory(systemProfilesPath); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 0ad8bca314..9b130fdfd8 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -102,7 +102,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index f6e0111b6d..41381d55bd 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { onStarted(); @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO); + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index a943efcc70..3633fa3e10 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV 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 = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index cb9801c178..2e51ac8071 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO)) + await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous)) { await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 817b1f8046..20a9a705b8 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public Stream GetStream() { - var stream = GetInputStream(TempFilePath, AsyncFile.UseAsyncIO); + var stream = GetInputStream(TempFilePath); bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; if (seekFile) { @@ -107,14 +107,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return stream; } - protected FileStream GetInputStream(string path, bool allowAsyncFileRead) + protected FileStream GetInputStream(string path) => new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, - allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan); + FileOptions.SequentialScan | FileOptions.Asynchronous); protected async Task DeleteTempFiles(string path, int retryCount = 0) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 84a878e517..3b69e55b01 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -118,7 +118,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await StreamHelper.CopyToAsync( stream, fileStream, diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index bcb2b50c7a..8a33b12f4c 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -206,7 +206,7 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index e6584f0fe6..741bdfee97 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers // For older files, assume fully static var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite; - FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); return File(stream, "text/plain; charset=utf-8"); } diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index f36769dc2a..4567621470 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -38,7 +38,7 @@ namespace Jellyfin.Api.Helpers FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, - (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan); + FileOptions.Asynchronous | FileOptions.SequentialScan); await using (fileStream.ConfigureAwait(false)) { using var reader = new StreamReader(fileStream); diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs index c570183514..61e18220a1 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs @@ -17,7 +17,6 @@ namespace Jellyfin.Api.Helpers private readonly TranscodingJobDto? _job; private readonly TranscodingJobHelper? _transcodingJobHelper; private readonly int _timeoutMs; - private readonly bool _allowAsyncFileRead; private int _bytesWritten; private bool _disposed; @@ -34,17 +33,7 @@ namespace Jellyfin.Api.Helpers _transcodingJobHelper = transcodingJobHelper; _timeoutMs = timeoutMs; - var fileOptions = FileOptions.SequentialScan; - _allowAsyncFileRead = false; - - // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - if (AsyncFile.UseAsyncIO) - { - fileOptions |= FileOptions.Asynchronous; - _allowAsyncFileRead = true; - } - - _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); + _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan); } /// @@ -57,7 +46,6 @@ namespace Jellyfin.Api.Helpers _job = null; _transcodingJobHelper = null; _timeoutMs = timeoutMs; - _allowAsyncFileRead = AsyncFile.UseAsyncIO; _stream = stream; } @@ -103,15 +91,7 @@ namespace Jellyfin.Api.Helpers while (remainingBytesToRead > 0) { cancellationToken.ThrowIfCancellationRequested(); - int bytesRead; - if (_allowAsyncFileRead) - { - bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false); - } - else - { - bytesRead = _stream.Read(buffer, newOffset, remainingBytesToRead); - } + int bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false); remainingBytesToRead -= bytesRead; newOffset += bytesRead; diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 4e1e98df0d..14f287aef6 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -557,7 +557,7 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 4abd5b36d1..f3fbab77e4 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -132,7 +132,7 @@ namespace Jellyfin.Server.Infrastructure FileAccess.Read, FileShare.ReadWrite, bufferSize: BufferSize, - options: (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan); + options: FileOptions.Asynchronous | FileOptions.SequentialScan); fileStream.Seek(offset, SeekOrigin.Begin); await StreamCopyOperation diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 1300ce3b67..f36675b955 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -547,7 +547,7 @@ namespace Jellyfin.Server ?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'"); // Copy the resource contents to the expected file path for the config file - await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await resource.CopyToAsync(dst).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f8451e92c3..022cdbe9d3 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -680,7 +680,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs index b888a41639..f38ed9ae3d 100644 --- a/MediaBrowser.Model/IO/AsyncFile.cs +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -8,20 +8,13 @@ namespace MediaBrowser.Model.IO /// public static class AsyncFile { - /// - /// Gets a value indicating whether we should use async IO on this platform. - /// . - /// - /// Returns false on Windows; otherwise true. - public static bool UseAsyncIO => !OperatingSystem.IsWindows(); - /// /// Opens an existing file for reading. /// /// The file to be opened for reading. /// A read-only on the specified path. public static FileStream OpenRead(string path) - => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, UseAsyncIO); + => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); /// /// Opens an existing file for writing. @@ -29,6 +22,6 @@ namespace MediaBrowser.Model.IO /// The file to be opened for writing. /// An unshared object on the specified path with Write access. public static FileStream OpenWrite(string path) - => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, UseAsyncIO); + => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); } } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 6c14c8de1e..7d259a9d36 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -264,7 +264,7 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 81529e9846..73bca5aa59 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index c1226febfc..3e0b0014eb 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index 8572b3413d..e0b2f9c588 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 1dea3dece1..479ae0f391 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -295,7 +295,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb imdbParam)); var rootObject = await GetDeserializedOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; @@ -335,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb seasonId)); var rootObject = await GetDeserializedOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 7a057c065f..7b2454efc9 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Studios Directory.CreateDirectory(Path.GetDirectoryName(file)); await using var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index d6c346ba12..772e617abb 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(savePath)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, AsyncFile.UseAsyncIO); + using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(fs).ConfigureAwait(false); return; -- cgit v1.2.3 From a4eede29abf1cf380c959835e59b7062ead1a654 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 25 Sep 2021 20:17:12 +0200 Subject: Use RandomAccess instead of a FileStream where it makes sense --- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 4 ++-- .../Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 1bc229b0ca..77da46cd6d 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -246,9 +246,9 @@ namespace Emby.Server.Implementations.IO { try { - using (Stream thisFileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1)) + using (var fileHandle = File.OpenHandle(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - result.Length = thisFileStream.Length; + result.Length = RandomAccess.GetLength(fileHandle); } } catch (FileNotFoundException ex) diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 4abd5b36d1..2296ac5c8a 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -55,8 +55,8 @@ namespace Jellyfin.Server.Infrastructure // This may or may not be fixed in .NET 6, but looks like it will not https://github.com/dotnet/aspnetcore/issues/34371 if ((fileInfo.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) { - using Stream thisFileStream = File.OpenRead(path); - length = thisFileStream.Length; + using var fileHandle = File.OpenHandle(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + length = RandomAccess.GetLength(fileHandle); } return new FileMetadata -- cgit v1.2.3 From 79642af3b8a9e2f001ae07902090b68e677bb949 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 25 Sep 2021 20:32:53 +0200 Subject: Fix some warnings --- .../Library/LiveStreamHelper.cs | 2 +- .../LiveTv/TunerHosts/BaseTunerHost.cs | 18 ++++++++++-------- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 3 ++- .../LiveTv/TunerHosts/LiveStream.cs | 18 +++++++++--------- .../Playlists/ManualPlaylistsFolder.cs | 18 +++++++++--------- Emby.Server.Implementations/Plugins/PluginManager.cs | 20 ++++++++++---------- 6 files changed, 41 insertions(+), 38 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 16b45161fd..83acd8e9f2 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -10,9 +10,9 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using Jellyfin.Extensions.Json; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 096b7f0454..2b82f24623 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -23,10 +23,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public abstract class BaseTunerHost { - protected readonly IServerConfigurationManager Config; - protected readonly ILogger Logger; - protected readonly IFileSystem FileSystem; - private readonly IMemoryCache _memoryCache; protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IFileSystem fileSystem, IMemoryCache memoryCache) @@ -37,12 +33,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts FileSystem = fileSystem; } - public virtual bool IsSupported => true; + protected IServerConfigurationManager Config { get; } - protected abstract Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken); + protected ILogger Logger { get; } + + protected IFileSystem FileSystem { get; } + + public virtual bool IsSupported => true; public abstract string Type { get; } + protected virtual string ChannelIdPrefix => Type + "_"; + + protected abstract Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken); + public async Task> GetChannels(TunerHostInfo tuner, bool enableCache, CancellationToken cancellationToken) { var key = tuner.Id; @@ -217,8 +221,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts throw new LiveTvConflictException(); } - protected virtual string ChannelIdPrefix => Type + "_"; - protected virtual bool IsValidChannelId(string channelId) { if (string.IsNullOrEmpty(channelId)) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 6a2e7f6998..31445e1ecc 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -101,7 +101,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - if (localAddress.IsIPv4MappedToIPv6) { + if (localAddress.IsIPv4MappedToIPv6) + { localAddress = localAddress.MapToIPv4(); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 817b1f8046..f024e49344 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -20,14 +20,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { private readonly IConfigurationManager _configurationManager; - protected readonly IFileSystem FileSystem; - - protected readonly IStreamHelper StreamHelper; - - protected string TempFilePath; - protected readonly ILogger Logger; - protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource(); - public LiveStream( MediaSourceInfo mediaSource, TunerHostInfo tuner, @@ -55,7 +47,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts SetTempFilePath("ts"); } - protected virtual int EmptyReadLimit => 1000; + protected IFileSystem FileSystem { get; } + + protected IStreamHelper StreamHelper { get; } + + protected ILogger Logger { get; } + + protected CancellationTokenSource LiveStreamCancellationTokenSource { get; } = new CancellationTokenSource(); + + protected string TempFilePath { get; set; } public MediaSourceInfo OriginalMediaSource { get; set; } diff --git a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs index 4160f3a500..8b1cee89d1 100644 --- a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs +++ b/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs @@ -17,6 +17,15 @@ namespace Emby.Server.Implementations.Playlists Name = "Playlists"; } + [JsonIgnore] + public override bool IsHidden => true; + + [JsonIgnore] + public override bool SupportsInheritedParentImages => false; + + [JsonIgnore] + public override string CollectionType => MediaBrowser.Model.Entities.CollectionType.Playlists; + public override bool IsVisible(User user) { return base.IsVisible(user) && GetChildren(user, true).Any(); @@ -27,15 +36,6 @@ namespace Emby.Server.Implementations.Playlists return base.GetEligibleChildrenForRecursiveChildren(user).OfType(); } - [JsonIgnore] - public override bool IsHidden => true; - - [JsonIgnore] - public override bool SupportsInheritedParentImages => false; - - [JsonIgnore] - public override string CollectionType => MediaBrowser.Model.Entities.CollectionType.Playlists; - protected override QueryResult GetItemsInternal(InternalItemsQuery query) { if (query.User == null) diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index b8e1dc2c05..d52c0b2a14 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -8,10 +8,10 @@ using System.Reflection; using System.Text; using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Common; -using MediaBrowser.Common.Extensions; using Jellyfin.Extensions.Json; using Jellyfin.Extensions.Json.Converters; +using MediaBrowser.Common; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; @@ -39,14 +39,6 @@ namespace Emby.Server.Implementations.Plugins private IHttpClientFactory? _httpClientFactory; - private IHttpClientFactory HttpClientFactory - { - get - { - return _httpClientFactory ?? (_httpClientFactory = _appHost.Resolve()); - } - } - /// /// Initializes a new instance of the class. /// @@ -86,6 +78,14 @@ namespace Emby.Server.Implementations.Plugins _plugins = Directory.Exists(_pluginsPath) ? DiscoverPlugins().ToList() : new List(); } + private IHttpClientFactory HttpClientFactory + { + get + { + return _httpClientFactory ??= _appHost.Resolve(); + } + } + /// /// Gets the Plugins. /// -- cgit v1.2.3