From f929dc92d128624007f5dfb7914c3167ae4d8712 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:34:25 -0500 Subject: [PATCH] update dependencies; code cleanup (#1357) * update dependencies * code cleanup --- .config/dotnet-tools.json | 2 +- .../Commands/RefreshChannelListHandler.cs | 1 - .../Playouts/Commands/BuildPlayoutHandler.cs | 7 +- .../ProgramScheduleItemCommandBase.cs | 4 +- .../ReplaceProgramScheduleItemsHandler.cs | 2 +- .../Commands/CreateCustomResolutionHandler.cs | 4 +- .../Commands/DeleteCustomResolutionHandler.cs | 2 +- .../Commands/RebuildSearchIndexHandler.cs | 4 +- ...layoutItemProcessByChannelNumberHandler.cs | 2 +- .../ExtractEmbeddedSubtitlesHandler.cs | 12 +- .../ErsatzTV.Core.Tests.csproj | 2 +- .../PlayoutModeSchedulerBaseTests.cs | 10 +- ErsatzTV.Core/Domain/Resolution.cs | 2 +- .../FFmpeg/FFmpegLibraryProcessService.cs | 10 +- .../Scheduling/IMediaCollectionEnumerator.cs | 4 +- .../ChronologicalMediaCollectionEnumerator.cs | 6 +- .../CustomOrderCollectionEnumerator.cs | 8 +- .../Scheduling/PlayoutModeSchedulerBase.cs | 4 +- .../PlayoutModeSchedulerDuration.cs | 10 +- .../Scheduling/PlayoutModeSchedulerFlood.cs | 2 +- .../PlayoutModeSchedulerMultiple.cs | 2 +- .../Scheduling/PlayoutModeSchedulerOne.cs | 2 +- .../RandomizedMediaCollectionEnumerator.cs | 8 +- .../SeasonEpisodeMediaCollectionEnumerator.cs | 8 +- .../ShuffleInOrderCollectionEnumerator.cs | 10 +- .../ShuffledMediaCollectionEnumerator.cs | 10 +- ErsatzTV.Core/SystemStartup.cs | 10 +- .../Vaapi/VaapiCapabilityParserTests.cs | 4 +- .../ErsatzTV.FFmpeg.Tests.csproj | 2 +- .../DefaultHardwareCapabilities.cs | 2 +- .../Capabilities/NoHardwareCapabilities.cs | 2 +- .../NvidiaHardwareCapabilities.cs | 6 +- .../Vaapi/VaapiCapabilityParser.cs | 2 +- .../Vaapi/VaapiProfileEntrypoint.cs | 5 +- .../Capabilities/VaapiHardwareCapabilities.cs | 220 ++++---- .../Encoder/Vaapi/EncoderH264Vaapi.cs | 8 +- .../Encoder/Vaapi/EncoderHevcVaapi.cs | 4 +- .../Encoder/Vaapi/EncoderMpeg2Vaapi.cs | 6 +- ErsatzTV.FFmpeg/Filter/ComplexFilter.cs | 5 +- ErsatzTV.FFmpeg/Option/Mp4OutputOptions.cs | 3 +- .../Pipeline/PipelineBuilderBase.cs | 2 +- .../Pipeline/QsvPipelineBuilder.cs | 2 +- .../Pipeline/VaapiPipelineBuilder.cs | 4 +- .../ErsatzTV.Infrastructure.Tests.csproj | 2 +- .../ErsatzTV.Infrastructure.csproj | 2 +- .../Locking/EntityLocker.cs | 2 +- ...MultiEpisodeShuffleCollectionEnumerator.cs | 10 +- .../Core/FFmpeg/TranscodingTests.cs | 6 +- .../ErsatzTV.Scanner.Tests.csproj | 2 +- ErsatzTV/Controllers/InternalController.cs | 2 +- ErsatzTV/ErsatzTV.csproj | 6 +- ErsatzTV/Pages/Index.razor | 10 +- ErsatzTV/Pages/Playouts.razor | 2 +- ErsatzTV/Pages/ScheduleItemsEditor.razor | 486 +++++++++--------- ErsatzTV/Pages/Search.razor | 424 +++++++-------- ErsatzTV/Pages/Settings.razor | 458 ++++++++--------- ErsatzTV/Pages/Trash.razor | 440 ++++++++-------- ErsatzTV/Program.cs | 5 +- ErsatzTV/Services/EmbyService.cs | 2 +- ErsatzTV/Services/FFmpegWorkerService.cs | 2 +- .../Services/RunOnce/CacheCleanerService.cs | 2 +- .../RunOnce/DatabaseMigratorService.cs | 2 +- ErsatzTV/Services/ScannerService.cs | 2 +- ErsatzTV/Services/SchedulerService.cs | 4 +- ErsatzTV/Services/SearchIndexService.cs | 2 +- ErsatzTV/Services/WorkerService.cs | 2 +- .../Shared/AddCustomResolutionDialog.razor | 15 +- ErsatzTV/Shared/MainLayout.razor | 5 +- .../ProgramScheduleItemEditViewModel.cs | 5 +- 69 files changed, 1166 insertions(+), 1159 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 397114406..d6ea8ea0d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2023.1.3", + "version": "2023.2.0", "commands": [ "jb" ] diff --git a/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs b/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs index 2573d0395..3b5dd8777 100644 --- a/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs +++ b/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs @@ -1,4 +1,3 @@ -using System.Data; using System.Data.Common; using System.Xml; using Dapper; diff --git a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs index 8a2915a62..94a39a22e 100644 --- a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs +++ b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs @@ -19,8 +19,8 @@ public class BuildPlayoutHandler : IRequestHandler _dbContextFactory; - private readonly IFFmpegSegmenterService _ffmpegSegmenterService; private readonly IEntityLocker _entityLocker; + private readonly IFFmpegSegmenterService _ffmpegSegmenterService; private readonly IPlayoutBuilder _playoutBuilder; private readonly ChannelWriter _workerChannel; @@ -112,7 +112,8 @@ public class BuildPlayoutHandler : IRequestHandler DiscardAttemptsMustBeValid(Playout playout) { - foreach (ProgramScheduleItemDuration item in playout.ProgramSchedule.Items.OfType()) + foreach (ProgramScheduleItemDuration item in + playout.ProgramSchedule.Items.OfType()) { item.DiscardToFillAttempts = item.PlaybackOrder switch { @@ -120,7 +121,7 @@ public class BuildPlayoutHandler : IRequestHandler 0 }; } - + return playout; } diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/ProgramScheduleItemCommandBase.cs b/ErsatzTV.Application/ProgramSchedules/Commands/ProgramScheduleItemCommandBase.cs index deab63833..0bcb5f770 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/ProgramScheduleItemCommandBase.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/ProgramScheduleItemCommandBase.cs @@ -253,7 +253,9 @@ public abstract class ProgramScheduleItemCommandBase PlaybackOrder = item.PlaybackOrder, PlayoutDuration = FixDuration(item.PlayoutDuration.GetValueOrDefault()), TailMode = item.TailMode, - DiscardToFillAttempts = FixDiscardToFillAttempts(item.PlaybackOrder, item.DiscardToFillAttempts.GetValueOrDefault()), + DiscardToFillAttempts = FixDiscardToFillAttempts( + item.PlaybackOrder, + item.DiscardToFillAttempts.GetValueOrDefault()), CustomTitle = item.CustomTitle, GuideMode = item.GuideMode, PreRollFillerId = item.PreRollFillerId, diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItemsHandler.cs b/ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItemsHandler.cs index 6cdd04f53..1fed7d638 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItemsHandler.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItemsHandler.cs @@ -29,7 +29,7 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); - return await validation.Apply(ps => PersistItems(dbContext, request, ps)); + return await LanguageExtensions.Apply(validation, ps => PersistItems(dbContext, request, ps)); } private async Task> PersistItems( diff --git a/ErsatzTV.Application/Resolutions/Commands/CreateCustomResolutionHandler.cs b/ErsatzTV.Application/Resolutions/Commands/CreateCustomResolutionHandler.cs index c32cc4e8e..da3fe9d5e 100644 --- a/ErsatzTV.Application/Resolutions/Commands/CreateCustomResolutionHandler.cs +++ b/ErsatzTV.Application/Resolutions/Commands/CreateCustomResolutionHandler.cs @@ -9,10 +9,8 @@ public class CreateCustomResolutionHandler : IRequestHandler _dbContextFactory; - public CreateCustomResolutionHandler(IDbContextFactory dbContextFactory) - { + public CreateCustomResolutionHandler(IDbContextFactory dbContextFactory) => _dbContextFactory = dbContextFactory; - } public async Task> Handle(CreateCustomResolution request, CancellationToken cancellationToken) { diff --git a/ErsatzTV.Application/Resolutions/Commands/DeleteCustomResolutionHandler.cs b/ErsatzTV.Application/Resolutions/Commands/DeleteCustomResolutionHandler.cs index 6853e68af..b8fd61340 100644 --- a/ErsatzTV.Application/Resolutions/Commands/DeleteCustomResolutionHandler.cs +++ b/ErsatzTV.Application/Resolutions/Commands/DeleteCustomResolutionHandler.cs @@ -28,7 +28,7 @@ public class DeleteCustomResolutionHandler : IRequestHandler { private readonly IConfigElementRepository _configElementRepository; private readonly IFallbackMetadataProvider _fallbackMetadataProvider; - private readonly SystemStartup _systemStartup; private readonly ILocalFileSystem _localFileSystem; private readonly ILogger _logger; private readonly ISearchIndex _searchIndex; private readonly ICachingSearchRepository _searchRepository; + private readonly SystemStartup _systemStartup; public RebuildSearchIndexHandler( ISearchIndex searchIndex, @@ -66,7 +66,7 @@ public class RebuildSearchIndexHandler : IRequestHandler { _logger.LogInformation("Search index is already version {Version}", _searchIndex.Version); } - + _systemStartup.SearchIndexIsReady(); } } diff --git a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs index 543fa1d30..0da765e95 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs @@ -462,7 +462,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< "Attempting to stream Plex file {PlexFileName} using key {PlexKey}", pmf.Path, pmf.Key); - + return new PlayoutItemWithPath( playoutItem, $"http://localhost:{Settings.ListenPort}/media/plex/{plexMediaSourceId}/{pmf.Key}"); diff --git a/ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs b/ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs index b83299cb5..e2f799190 100644 --- a/ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs +++ b/ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs @@ -21,8 +21,8 @@ namespace ErsatzTV.Application.Subtitles; public class ExtractEmbeddedSubtitlesHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; - private readonly ILocalFileSystem _localFileSystem; private readonly IEntityLocker _entityLocker; + private readonly ILocalFileSystem _localFileSystem; private readonly ILogger _logger; private readonly ChannelWriter _workerChannel; @@ -74,7 +74,8 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler p.Channel.SubtitleMode != ChannelSubtitleMode.None || - p.ProgramSchedule.Items.Any(psi => psi.SubtitleMode != null && psi.SubtitleMode != ChannelSubtitleMode.None)) + p.ProgramSchedule.Items.Any( + psi => psi.SubtitleMode != null && psi.SubtitleMode != ChannelSubtitleMode.None)) .SelectOneAsync(p => p.Id, p => p.Id == request.PlayoutId.IfNone(-1)); playoutIdsToCheck.AddRange(requestedPlayout.Map(p => p.Id)); @@ -86,7 +87,8 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler p.Channel.SubtitleMode != ChannelSubtitleMode.None || - p.ProgramSchedule.Items.Any(psi => psi.SubtitleMode != null && psi.SubtitleMode != ChannelSubtitleMode.None)) + p.ProgramSchedule.Items.Any( + psi => psi.SubtitleMode != null && psi.SubtitleMode != ChannelSubtitleMode.None)) .Map(p => p.Id) .ToList(); } @@ -109,7 +111,7 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs index 2a4c742e0..7bcf861b6 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs @@ -58,7 +58,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase scheduleItem, new PlayoutItem(), new List(), - log: true, + true, _cancellationToken); playoutItems.Count.Should().Be(1); @@ -111,7 +111,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase scheduleItem, new PlayoutItem(), new List { new() }, - log: true, + true, _cancellationToken); playoutItems.Count.Should().Be(1); @@ -178,7 +178,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) }, new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(60) } }, - log: true, + true, _cancellationToken); playoutItems.Count.Should().Be(3); @@ -270,7 +270,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) }, new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) } }, - log: true, + true, _cancellationToken); playoutItems.Count.Should().Be(5); @@ -376,7 +376,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) }, new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) } }, - log: true, + true, _cancellationToken); playoutItems.Count.Should().Be(5); diff --git a/ErsatzTV.Core/Domain/Resolution.cs b/ErsatzTV.Core/Domain/Resolution.cs index 131b882b7..fe8979cf6 100644 --- a/ErsatzTV.Core/Domain/Resolution.cs +++ b/ErsatzTV.Core/Domain/Resolution.cs @@ -6,9 +6,9 @@ public class Resolution : IDisplaySize { public int Id { get; set; } public string Name { get; set; } + public bool IsCustom { get; set; } public int Height { get; set; } public int Width { get; set; } - public bool IsCustom { get; set; } public override string ToString() => $"{Width}x{Height}"; } diff --git a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs index c0c997067..aba167716 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs @@ -16,11 +16,11 @@ namespace ErsatzTV.Core.FFmpeg; public class FFmpegLibraryProcessService : IFFmpegProcessService { + private readonly IConfigElementRepository _configElementRepository; private readonly FFmpegProcessService _ffmpegProcessService; private readonly IFFmpegStreamSelector _ffmpegStreamSelector; private readonly ILogger _logger; private readonly IPipelineBuilderFactory _pipelineBuilderFactory; - private readonly IConfigElementRepository _configElementRepository; private readonly FFmpegPlaybackSettingsCalculator _playbackSettingsCalculator; private readonly ITempFilePool _tempFilePool; @@ -95,8 +95,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService hlsRealtime, targetFramerate); - var allSubtitles = await getSubtitles(playbackSettings); - + List allSubtitles = await getSubtitles(playbackSettings); + Option maybeSubtitle = await _ffmpegStreamSelector.SelectSubtitleStream( allSubtitles, @@ -208,7 +208,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService { // use mpeg-ts by default outputFormat = OutputFormatKind.MpegTs; - + // override with setting if applicable Option maybeOutputFormat = await _configElementRepository .GetValue(ConfigElementKey.FFmpegHlsDirectOutputFormat); @@ -269,7 +269,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService { return None; } - + // hls direct won't use extracted embedded subtitles if (subtitle.SubtitleKind == SubtitleKind.Embedded) { diff --git a/ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs b/ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs index 3a6c210ec..4318d4416 100644 --- a/ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs @@ -4,10 +4,10 @@ namespace ErsatzTV.Core.Interfaces.Scheduling; public interface IMediaCollectionEnumerator { - void ResetState(CollectionEnumeratorState state); CollectionEnumeratorState State { get; } Option Current { get; } - void MoveNext(); int Count { get; } Option MinimumDuration { get; } + void ResetState(CollectionEnumeratorState state); + void MoveNext(); } diff --git a/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs index 60c52bc67..366469bb0 100644 --- a/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs @@ -6,8 +6,8 @@ namespace ErsatzTV.Core.Scheduling; public sealed class ChronologicalMediaCollectionEnumerator : IMediaCollectionEnumerator { - private readonly IList _sortedMediaItems; private readonly Lazy> _lazyMinimumDuration; + private readonly IList _sortedMediaItems; public ChronologicalMediaCollectionEnumerator( IEnumerable mediaItems, @@ -31,11 +31,9 @@ public sealed class ChronologicalMediaCollectionEnumerator : IMediaCollectionEnu } } - public void ResetState(CollectionEnumeratorState state) - { + public void ResetState(CollectionEnumeratorState state) => // seed doesn't matter in chronological State.Index = state.Index; - } public CollectionEnumeratorState State { get; } diff --git a/ErsatzTV.Core/Scheduling/CustomOrderCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/CustomOrderCollectionEnumerator.cs index b311a829a..ddaef5baa 100644 --- a/ErsatzTV.Core/Scheduling/CustomOrderCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/CustomOrderCollectionEnumerator.cs @@ -7,10 +7,10 @@ namespace ErsatzTV.Core.Scheduling; public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator { private readonly Collection _collection; + private readonly Lazy> _lazyMinimumDuration; private readonly IList _mediaItems; private readonly IList _sortedMediaItems; - private readonly Lazy> _lazyMinimumDuration; public CustomOrderCollectionEnumerator( Collection collection, @@ -35,11 +35,9 @@ public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator } } - public void ResetState(CollectionEnumeratorState state) - { + public void ResetState(CollectionEnumeratorState state) => // seed doesn't matter here State.Index = state.Index; - } public CollectionEnumeratorState State { get; } @@ -48,6 +46,6 @@ public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count; public Option MinimumDuration => _lazyMinimumDuration.Value; - + public int Count => _sortedMediaItems.Count; } diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs index d4ea15ac9..09dbf8988 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs @@ -4,8 +4,6 @@ using ErsatzTV.Core.Extensions; using ErsatzTV.Core.Interfaces.Scheduling; using LanguageExt.UnsafeValueAccess; using Microsoft.Extensions.Logging; -using Serilog; -using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ErsatzTV.Core.Scheduling; @@ -606,7 +604,7 @@ public abstract class PlayoutModeSchedulerBase : IPlayoutModeScheduler whe } } } - + return result; } diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs index 85a4b22f6..d3301fc15 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs @@ -26,7 +26,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase durationUntil = None; - int discardAttempts = 0; + var discardAttempts = 0; IMediaCollectionEnumerator contentEnumerator = collectionEnumerators[CollectionKey.ForScheduleItem(scheduleItem)]; @@ -121,7 +121,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase playoutItem.GuideFinish = du.UtcDateTime); DateTimeOffset durationFinish = nextState.DurationFinish.IfNone(SystemTime.MaxValueUtc); - + var enumeratorStates = new Dictionary(); foreach ((CollectionKey key, IMediaCollectionEnumerator enumerator) in collectionEnumerators) { @@ -134,9 +134,9 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase pi.FinishOffset); willFinishInTime = itemStartTime > durationFinish || @@ -165,7 +165,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase scheduleItem.PlayoutDuration) { diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs index e92fc9b0d..a87421523 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs @@ -86,7 +86,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase pi.FinishOffset); diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs index 7cc950cd8..680d4c11e 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs @@ -85,7 +85,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase _mediaItems; private readonly Lazy> _lazyMinimumDuration; + private readonly IList _mediaItems; private readonly Random _random; private int _index; @@ -27,11 +27,9 @@ public class RandomizedMediaCollectionEnumerator : IMediaCollectionEnumerator } } - public void ResetState(CollectionEnumeratorState state) - { + public void ResetState(CollectionEnumeratorState state) => // seed never changes here, no need to reset State.Index = state.Index; - } public CollectionEnumeratorState State { get; } @@ -44,6 +42,6 @@ public class RandomizedMediaCollectionEnumerator : IMediaCollectionEnumerator } public Option MinimumDuration => _lazyMinimumDuration.Value; - + public int Count => _mediaItems.Count; } diff --git a/ErsatzTV.Core/Scheduling/SeasonEpisodeMediaCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/SeasonEpisodeMediaCollectionEnumerator.cs index fc3f46941..235f4c87c 100644 --- a/ErsatzTV.Core/Scheduling/SeasonEpisodeMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/SeasonEpisodeMediaCollectionEnumerator.cs @@ -6,8 +6,8 @@ namespace ErsatzTV.Core.Scheduling; public sealed class SeasonEpisodeMediaCollectionEnumerator : IMediaCollectionEnumerator { - private readonly IList _sortedMediaItems; private readonly Lazy> _lazyMinimumDuration; + private readonly IList _sortedMediaItems; public SeasonEpisodeMediaCollectionEnumerator( IEnumerable mediaItems, @@ -31,11 +31,9 @@ public sealed class SeasonEpisodeMediaCollectionEnumerator : IMediaCollectionEnu } } - public void ResetState(CollectionEnumeratorState state) - { + public void ResetState(CollectionEnumeratorState state) => // seed doesn't matter here State.Index = state.Index; - } public CollectionEnumeratorState State { get; } @@ -44,6 +42,6 @@ public sealed class SeasonEpisodeMediaCollectionEnumerator : IMediaCollectionEnu public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count; public Option MinimumDuration => _lazyMinimumDuration.Value; - + public int Count => _sortedMediaItems.Count; } diff --git a/ErsatzTV.Core/Scheduling/ShuffleInOrderCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/ShuffleInOrderCollectionEnumerator.cs index f712e4258..294a2d5b1 100644 --- a/ErsatzTV.Core/Scheduling/ShuffleInOrderCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/ShuffleInOrderCollectionEnumerator.cs @@ -8,11 +8,11 @@ public class ShuffleInOrderCollectionEnumerator : IMediaCollectionEnumerator { private readonly CancellationToken _cancellationToken; private readonly IList _collections; + private readonly Lazy> _lazyMinimumDuration; private readonly int _mediaItemCount; private readonly bool _randomStartPoint; private Random _random; private IList _shuffled; - private readonly Lazy> _lazyMinimumDuration; public ShuffleInOrderCollectionEnumerator( IList collections, @@ -82,6 +82,10 @@ public class ShuffleInOrderCollectionEnumerator : IMediaCollectionEnumerator State.Index %= _shuffled.Count; } + public Option MinimumDuration => _lazyMinimumDuration.Value; + + public int Count => _shuffled.Count; + private IList Shuffle(IList collections, Random random) { // based on https://keyj.emphy.de/balanced-shuffle/ @@ -217,8 +221,4 @@ public class ShuffleInOrderCollectionEnumerator : IMediaCollectionEnumerator public int Index { get; set; } public IList> Items { get; set; } } - - public Option MinimumDuration => _lazyMinimumDuration.Value; - - public int Count => _shuffled.Count; } diff --git a/ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs index 691e3caf1..5113b6edd 100644 --- a/ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs @@ -7,9 +7,9 @@ namespace ErsatzTV.Core.Scheduling; public class ShuffledMediaCollectionEnumerator : IMediaCollectionEnumerator { private readonly CancellationToken _cancellationToken; + private readonly Lazy> _lazyMinimumDuration; private readonly int _mediaItemCount; private readonly IList _mediaItems; - private readonly Lazy> _lazyMinimumDuration; private CloneableRandom _random; private IList _shuffled; @@ -79,6 +79,10 @@ public class ShuffledMediaCollectionEnumerator : IMediaCollectionEnumerator State.Index %= _mediaItemCount; } + public Option MinimumDuration => _lazyMinimumDuration.Value; + + public int Count => _shuffled.Count; + private IList Shuffle(IEnumerable list, CloneableRandom random) { GroupedMediaItem[] copy = list.ToArray(); @@ -93,8 +97,4 @@ public class ShuffledMediaCollectionEnumerator : IMediaCollectionEnumerator return GroupedMediaItem.FlattenGroups(copy, _mediaItemCount); } - - public Option MinimumDuration => _lazyMinimumDuration.Value; - - public int Count => _shuffled.Count; } diff --git a/ErsatzTV.Core/SystemStartup.cs b/ErsatzTV.Core/SystemStartup.cs index 189b3781b..620b6e051 100644 --- a/ErsatzTV.Core/SystemStartup.cs +++ b/ErsatzTV.Core/SystemStartup.cs @@ -5,15 +5,15 @@ public class SystemStartup private readonly SemaphoreSlim _databaseStartup = new(0, 100); private readonly SemaphoreSlim _searchIndexStartup = new(0, 100); - public event EventHandler OnDatabaseReady; - public event EventHandler OnSearchIndexReady; - public bool IsDatabaseReady { get; private set; } public bool IsSearchIndexReady { get; private set; } + public event EventHandler OnDatabaseReady; + public event EventHandler OnSearchIndexReady; + public async Task WaitForDatabase(CancellationToken cancellationToken) => await _databaseStartup.WaitAsync(cancellationToken); - + public async Task WaitForSearchIndex(CancellationToken cancellationToken) => await _searchIndexStartup.WaitAsync(cancellationToken); @@ -23,7 +23,7 @@ public class SystemStartup IsDatabaseReady = true; OnDatabaseReady?.Invoke(this, EventArgs.Empty); } - + public void SearchIndexIsReady() { _searchIndexStartup.Release(100); diff --git a/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs b/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs index fba5becd0..c2b1d45f0 100644 --- a/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs +++ b/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs @@ -178,7 +178,7 @@ VAProfileNone/VAEntrypointVideoProc VA_RT_FORMAT_YUV420_10 VA_RT_FORMAT_RGB32 VA_RT_FORMAT_YUV420_10BPP"; - + [Test] public void ShouldParseEntrypoints() { @@ -188,7 +188,7 @@ VAProfileNone/VAEntrypointVideoProc brief.Count.Should().Be(20); full.Count.Should().Be(20); } - + [Test] public void Full_ShouldParseRateControlModes() { diff --git a/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj b/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj index a5f11bc3b..3bb6e3dad 100644 --- a/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj +++ b/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/ErsatzTV.FFmpeg/Capabilities/DefaultHardwareCapabilities.cs b/ErsatzTV.FFmpeg/Capabilities/DefaultHardwareCapabilities.cs index c3cc39067..fe214a5db 100644 --- a/ErsatzTV.FFmpeg/Capabilities/DefaultHardwareCapabilities.cs +++ b/ErsatzTV.FFmpeg/Capabilities/DefaultHardwareCapabilities.cs @@ -35,7 +35,7 @@ public class DefaultHardwareCapabilities : IHardwareCapabilities _ => FFmpegCapability.Hardware }; } - + public Option GetRateControlMode(string videoFormat, Option maybePixelFormat) => Option.None; } diff --git a/ErsatzTV.FFmpeg/Capabilities/NoHardwareCapabilities.cs b/ErsatzTV.FFmpeg/Capabilities/NoHardwareCapabilities.cs index 6667b7843..347e42336 100644 --- a/ErsatzTV.FFmpeg/Capabilities/NoHardwareCapabilities.cs +++ b/ErsatzTV.FFmpeg/Capabilities/NoHardwareCapabilities.cs @@ -15,7 +15,7 @@ public class NoHardwareCapabilities : IHardwareCapabilities Option videoProfile, Option maybePixelFormat) => FFmpegCapability.Software; - + public Option GetRateControlMode(string videoFormat, Option maybePixelFormat) => Option.None; } diff --git a/ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs b/ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs index c10f18afb..5be56e204 100644 --- a/ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs +++ b/ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs @@ -105,6 +105,9 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities return isHardware ? FFmpegCapability.Hardware : FFmpegCapability.Software; } + public Option GetRateControlMode(string videoFormat, Option maybePixelFormat) => + Option.None; + private FFmpegCapability CheckHardwareCodec(string codec, Func check) { if (check(codec)) @@ -115,7 +118,4 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities _logger.LogWarning("FFmpeg does not contain codec {Codec}; will fall back to software codec", codec); return FFmpegCapability.Software; } - - public Option GetRateControlMode(string videoFormat, Option maybePixelFormat) => - Option.None; } diff --git a/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiCapabilityParser.cs b/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiCapabilityParser.cs index c0ab8609a..b015e5f5b 100644 --- a/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiCapabilityParser.cs +++ b/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiCapabilityParser.cs @@ -23,7 +23,7 @@ public static class VaapiCapabilityParser return profileEntrypoints; } - + public static List ParseFull(string output) { var profileEntrypoints = new List(); diff --git a/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiProfileEntrypoint.cs b/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiProfileEntrypoint.cs index c8017aa5f..cdce22ce1 100644 --- a/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiProfileEntrypoint.cs +++ b/ErsatzTV.FFmpeg/Capabilities/Vaapi/VaapiProfileEntrypoint.cs @@ -6,8 +6,5 @@ public record VaapiProfileEntrypoint(string VaapiProfile, string VaapiEntrypoint public IReadOnlyCollection RateControlModes => _rateControlModes; - public bool AddRateControlMode(RateControlMode mode) - { - return _rateControlModes.Add(mode); - } + public bool AddRateControlMode(RateControlMode mode) => _rateControlModes.Add(mode); } diff --git a/ErsatzTV.FFmpeg/Capabilities/VaapiHardwareCapabilities.cs b/ErsatzTV.FFmpeg/Capabilities/VaapiHardwareCapabilities.cs index f11b404e1..794e50bb8 100644 --- a/ErsatzTV.FFmpeg/Capabilities/VaapiHardwareCapabilities.cs +++ b/ErsatzTV.FFmpeg/Capabilities/VaapiHardwareCapabilities.cs @@ -31,116 +31,132 @@ public class VaapiHardwareCapabilities : IHardwareCapabilities (VideoFormat.H264, "baseline" or "66") => false, (VideoFormat.H264, "main" or "77") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.H264Main, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.H264Main, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.H264, "high" or "100") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.H264High, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.H264High, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.H264, "high 10" or "110") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.H264High, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.H264High, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.H264, "baseline constrained" or "578") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.H264ConstrainedBaseline, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.H264ConstrainedBaseline, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Mpeg2Video, "main" or "4") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Mpeg2Main, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Mpeg2Main, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Mpeg2Video, "simple" or "5") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Mpeg2Simple, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Mpeg2Simple, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vc1, "simple" or "0") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vc1Simple, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vc1Simple, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vc1, "main" or "1") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vc1Main, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vc1Main, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vc1, "advanced" or "3") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vc1Advanced, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vc1Advanced, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Hevc, "main" or "1") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.HevcMain, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.HevcMain, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Hevc, "main 10" or "2") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.HevcMain10, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.HevcMain10, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vp9, "profile 0" or "0") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vp9Profile0, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vp9Profile0, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vp9, "profile 1" or "1") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vp9Profile1, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vp9Profile1, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vp9, "profile 2" or "2") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vp9Profile2, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vp9Profile2, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Vp9, "profile 3" or "3") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Vp9Profile3, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Vp9Profile3, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), (VideoFormat.Av1, "main" or "0") => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Av1Profile0, - VaapiEntrypoint: VaapiEntrypoint.Decode - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Av1Profile0, + VaapiEntrypoint: VaapiEntrypoint.Decode + }), // fall back to software decoder _ => false @@ -170,32 +186,36 @@ public class VaapiHardwareCapabilities : IHardwareCapabilities VideoFormat.H264 when bitDepth == 10 => false, VideoFormat.H264 => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.H264Main, - VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.H264Main, + VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower + }), VideoFormat.Hevc when bitDepth == 10 => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.HevcMain10, - VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.HevcMain10, + VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower + }), VideoFormat.Hevc => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.HevcMain, - VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.HevcMain, + VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower + }), VideoFormat.Mpeg2Video => - _profileEntrypoints.Any(e => e is - { - VaapiProfile: VaapiProfile.Mpeg2Main, - VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower - }), + _profileEntrypoints.Any( + e => e is + { + VaapiProfile: VaapiProfile.Mpeg2Main, + VaapiEntrypoint: VaapiEntrypoint.Encode or VaapiEntrypoint.EncodeLowPower + }), _ => false }; diff --git a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs index 7db2f52e4..0508bdbaf 100644 --- a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs +++ b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs @@ -7,11 +7,11 @@ public class EncoderH264Vaapi : EncoderBase private readonly RateControlMode _rateControlMode; public EncoderH264Vaapi(RateControlMode rateControlMode) => _rateControlMode = rateControlMode; - + public override string Name => "h264_vaapi"; - + public override StreamKind Kind => StreamKind.Video; - + public override IList OutputOptions { get @@ -23,7 +23,7 @@ public class EncoderH264Vaapi : EncoderBase result.Add("-rc_mode"); result.Add("1"); } - + return result; } } diff --git a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderHevcVaapi.cs b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderHevcVaapi.cs index 485960c51..dc1c5471b 100644 --- a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderHevcVaapi.cs +++ b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderHevcVaapi.cs @@ -9,7 +9,7 @@ public class EncoderHevcVaapi : EncoderBase public EncoderHevcVaapi(RateControlMode rateControlMode) => _rateControlMode = rateControlMode; public override string Name => "hevc_vaapi"; - + public override StreamKind Kind => StreamKind.Video; public override IList OutputOptions @@ -23,7 +23,7 @@ public class EncoderHevcVaapi : EncoderBase result.Add("-rc_mode"); result.Add("1"); } - + return result; } } diff --git a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderMpeg2Vaapi.cs b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderMpeg2Vaapi.cs index b78598a34..6910bfd62 100644 --- a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderMpeg2Vaapi.cs +++ b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderMpeg2Vaapi.cs @@ -9,9 +9,9 @@ public class EncoderMpeg2Vaapi : EncoderBase public EncoderMpeg2Vaapi(RateControlMode rateControlMode) => _rateControlMode = rateControlMode; public override string Name => "mpeg2_vaapi"; - + public override StreamKind Kind => StreamKind.Video; - + public override IList OutputOptions { get @@ -23,7 +23,7 @@ public class EncoderMpeg2Vaapi : EncoderBase result.Add("-rc_mode"); result.Add("1"); } - + return result; } } diff --git a/ErsatzTV.FFmpeg/Filter/ComplexFilter.cs b/ErsatzTV.FFmpeg/Filter/ComplexFilter.cs index 629287ea0..c2f27720b 100644 --- a/ErsatzTV.FFmpeg/Filter/ComplexFilter.cs +++ b/ErsatzTV.FFmpeg/Filter/ComplexFilter.cs @@ -238,7 +238,10 @@ public class ComplexFilter : IPipelineStep foreach (SubtitleInputFile subtitleInputFile in _maybeSubtitleInputFile.Filter( s => s.Method == SubtitleMethod.Copy || - s is { IsImageBased: true, Method: SubtitleMethod.Convert })) // TODO: support converting text subtitles? + s is + { + IsImageBased: true, Method: SubtitleMethod.Convert + })) // TODO: support converting text subtitles? { if (subtitleInputFile.Streams.Any()) { diff --git a/ErsatzTV.FFmpeg/Option/Mp4OutputOptions.cs b/ErsatzTV.FFmpeg/Option/Mp4OutputOptions.cs index 39f8a4a6a..fa86eda31 100644 --- a/ErsatzTV.FFmpeg/Option/Mp4OutputOptions.cs +++ b/ErsatzTV.FFmpeg/Option/Mp4OutputOptions.cs @@ -2,5 +2,6 @@ public class Mp4OutputOptions : OutputOption { - public override IList OutputOptions => new List { "-movflags", "+faststart+frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov+delay_moov" }; + public override IList OutputOptions => new List + { "-movflags", "+faststart+frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov+delay_moov" }; } diff --git a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs index 199b54f32..3aec26ff1 100644 --- a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs +++ b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs @@ -146,7 +146,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder { outputOption = new Mp4OutputOptions(); } - + var pipelineSteps = new List { new NoStandardInputOption(), diff --git a/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs index 4e91d5437..42e4b96bc 100644 --- a/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs @@ -491,7 +491,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder pf = availablePixelFormat; } } - + // only scale if scaling or padding was used for main video stream if (videoInputFile.FilterSteps.Any(s => s is ScaleFilter or ScaleFilter or PadFilter)) { diff --git a/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs index a63029327..ae99eb838 100644 --- a/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs @@ -200,7 +200,7 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder RateControlMode rateControlMode = _hardwareCapabilities.GetRateControlMode(desiredState.VideoFormat, desiredState.PixelFormat) .IfNone(RateControlMode.VBR); - + Option maybeEncoder = (ffmpegState.EncoderHardwareAccelerationMode, desiredState.VideoFormat) switch { @@ -425,7 +425,7 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder var downloadFilter = new HardwareDownloadFilter(currentState); currentState = downloadFilter.NextState(currentState); videoInputFile.FilterSteps.Add(downloadFilter); - + foreach (IPixelFormat pixelFormat in desiredState.PixelFormat) { IPixelFormat pf = pixelFormat; diff --git a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj index a04468bcf..5603d8b7a 100644 --- a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj +++ b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj index 6c8640179..59b62c4a1 100644 --- a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj +++ b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj @@ -11,7 +11,7 @@ - + diff --git a/ErsatzTV.Infrastructure/Locking/EntityLocker.cs b/ErsatzTV.Infrastructure/Locking/EntityLocker.cs index 2cac6452f..2c585fe9b 100644 --- a/ErsatzTV.Infrastructure/Locking/EntityLocker.cs +++ b/ErsatzTV.Infrastructure/Locking/EntityLocker.cs @@ -158,7 +158,7 @@ public class EntityLocker : IEntityLocker } public bool AreEmbyCollectionsLocked() => _embyCollections; - + public bool LockPlayout(int playoutId) { if (!_lockedPlayouts.ContainsKey(playoutId) && _lockedPlayouts.TryAdd(playoutId, 0)) diff --git a/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs b/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs index 6da9ddbbf..094055043 100644 --- a/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs +++ b/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs @@ -10,13 +10,13 @@ namespace ErsatzTV.Infrastructure.Scheduling; public class MultiEpisodeShuffleCollectionEnumerator : IMediaCollectionEnumerator { private readonly CancellationToken _cancellationToken; + private readonly Lazy> _lazyMinimumDuration; private readonly ILogger _logger; private readonly int _mediaItemCount; private readonly Dictionary> _mediaItemGroups; private readonly List _ungrouped; private CloneableRandom _random; private IList _shuffled; - private readonly Lazy> _lazyMinimumDuration; public MultiEpisodeShuffleCollectionEnumerator( ICollection mediaItems, @@ -126,6 +126,10 @@ public class MultiEpisodeShuffleCollectionEnumerator : IMediaCollectionEnumerato State.Index %= _mediaItemCount; } + public Option MinimumDuration => _lazyMinimumDuration.Value; + + public int Count => _shuffled.Count; + private IList Shuffle(CloneableRandom random) { int maxGroupNumber = _mediaItemGroups.Max(a => a.Key); @@ -188,8 +192,4 @@ public class MultiEpisodeShuffleCollectionEnumerator : IMediaCollectionEnumerato return copy; } - - public Option MinimumDuration => _lazyMinimumDuration.Value; - - public int Count => _shuffled.Count; } diff --git a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs index 6eeeca9b9..8b706377b 100644 --- a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs @@ -152,7 +152,7 @@ public class TranscodingTests new("mpeg2video", "yuv420p"), // // new("libx265", "yuv420p"), - new("libx265", "yuv420p10le"), + new("libx265", "yuv420p10le") // // new("mpeg4", "yuv420p"), // @@ -191,7 +191,7 @@ public class TranscodingTests { HardwareAccelerationKind.None, // HardwareAccelerationKind.Nvenc, - HardwareAccelerationKind.Vaapi, + HardwareAccelerationKind.Vaapi // HardwareAccelerationKind.Qsv // HardwareAccelerationKind.VideoToolbox, // HardwareAccelerationKind.Amf @@ -744,7 +744,7 @@ public class TranscodingTests .WithArguments(args) .WithValidation(CommandResultValidation.None) .ExecuteBufferedAsync(); - + string output = string.IsNullOrWhiteSpace(p1.StandardOutput) ? p1.StandardError : p1.StandardOutput; diff --git a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj index e8dba130a..8529a045e 100644 --- a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj +++ b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/ErsatzTV/Controllers/InternalController.cs b/ErsatzTV/Controllers/InternalController.cs index cf592d0d3..e99cdd9e0 100644 --- a/ErsatzTV/Controllers/InternalController.cs +++ b/ErsatzTV/Controllers/InternalController.cs @@ -78,7 +78,7 @@ public class InternalController : ControllerBase { contentType = "video/mp4"; } - + process.Start(); return new FileStreamResult(process.StandardOutput.BaseStream, contentType); }, diff --git a/ErsatzTV/ErsatzTV.csproj b/ErsatzTV/ErsatzTV.csproj index 4777b5b25..bc4fcc205 100644 --- a/ErsatzTV/ErsatzTV.csproj +++ b/ErsatzTV/ErsatzTV.csproj @@ -57,9 +57,9 @@ - + - + @@ -73,7 +73,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/ErsatzTV/Pages/Index.razor b/ErsatzTV/Pages/Index.razor index 025d7fb06..b0b8a2bea 100644 --- a/ErsatzTV/Pages/Index.razor +++ b/ErsatzTV/Pages/Index.razor @@ -105,7 +105,8 @@ } - } + + } @code { @@ -128,11 +129,8 @@ _cts.Cancel(); _cts.Dispose(); } - - private async void OnStartupProgress(object sender, EventArgs e) - { - await InvokeAsync(StateHasChanged); - } + + private async void OnStartupProgress(object sender, EventArgs e) => await InvokeAsync(StateHasChanged); protected override async Task OnParametersSetAsync() { diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor index 9b13ddd40..a41e4ffb1 100644 --- a/ErsatzTV/Pages/Playouts.razor +++ b/ErsatzTV/Pages/Playouts.razor @@ -149,7 +149,7 @@ _cts.Cancel(); _cts.Dispose(); } - + protected override void OnInitialized() => EntityLocker.OnPlayoutChanged += ReloadDetailsIfNeeded; protected override async Task OnParametersSetAsync() diff --git a/ErsatzTV/Pages/ScheduleItemsEditor.razor b/ErsatzTV/Pages/ScheduleItemsEditor.razor index 2ca3ffd70..7ba2b6348 100644 --- a/ErsatzTV/Pages/ScheduleItemsEditor.razor +++ b/ErsatzTV/Pages/ScheduleItemsEditor.razor @@ -89,249 +89,249 @@ @if (_selectedItem is not null) { - -
-
- - - - Dynamic - @if (!_schedule.ShuffleScheduleItems) - { - Fixed - } - - - - Collection - Television Show - Television Season - Artist - Multi Collection - Smart Collection - - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) - { - - - - Only the first 20 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist) - { - - - - Only the first 10 items are shown - - - - } - - @switch (_selectedItem.CollectionType) - { - case ProgramScheduleItemCollectionType.MultiCollection: - Shuffle - Shuffle In Order - break; - case ProgramScheduleItemCollectionType.Collection: - case ProgramScheduleItemCollectionType.SmartCollection: - Chronological - Random - Shuffle - Shuffle In Order - break; - case ProgramScheduleItemCollectionType.TelevisionShow: - Chronological - Season, Episode - Random - Shuffle - Multi-Episode Shuffle - break; - default: - Chronological - Random - Shuffle - break; - } - - - @if (!_schedule.ShuffleScheduleItems) - { - Flood - } - One - Multiple - Duration - - - - - (none) - Offline - Filler - - - - - Normal - Filler - - - -
-
- - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback)) - { - @filler.Name - } - - - - - - - @foreach (WatermarkViewModel watermark in _watermarks) - { - @watermark.Name - } - - - (none) - @foreach (CultureInfo culture in _availableCultures) - { - @culture.EnglishName - } - - - - (none) - @foreach (CultureInfo culture in _availableCultures) - { - @culture.EnglishName - } - - - None - Forced - Default - Any - - - -
-
+ +
+
+ + + + Dynamic + @if (!_schedule.ShuffleScheduleItems) + { + Fixed + } + + + + Collection + Television Show + Television Season + Artist + Multi Collection + Smart Collection + + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) + { + + + + Only the first 20 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist) + { + + + + Only the first 10 items are shown + + + + } + + @switch (_selectedItem.CollectionType) + { + case ProgramScheduleItemCollectionType.MultiCollection: + Shuffle + Shuffle In Order + break; + case ProgramScheduleItemCollectionType.Collection: + case ProgramScheduleItemCollectionType.SmartCollection: + Chronological + Random + Shuffle + Shuffle In Order + break; + case ProgramScheduleItemCollectionType.TelevisionShow: + Chronological + Season, Episode + Random + Shuffle + Multi-Episode Shuffle + break; + default: + Chronological + Random + Shuffle + break; + } + + + @if (!_schedule.ShuffleScheduleItems) + { + Flood + } + One + Multiple + Duration + + + + + (none) + Offline + Filler + + + + + Normal + Filler + + + +
+
+ + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback)) + { + @filler.Name + } + + + + + + + @foreach (WatermarkViewModel watermark in _watermarks) + { + @watermark.Name + } + + + (none) + @foreach (CultureInfo culture in _availableCultures) + { + @culture.EnglishName + } + + + + (none) + @foreach (CultureInfo culture in _availableCultures) + { + @culture.EnglishName + } + + + None + Forced + Default + Any + + + +
+
} diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index 58b450113..fc8360bad 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -92,226 +92,226 @@ -@if (_movies?.Count > 0) -{ -
- - Movies - - @if (_movies.Count > 50) - { - See All >> - } -
+ @if (_movies?.Count > 0) + { +
+ + Movies + + @if (_movies.Count > 50) + { + See All >> + } +
- - @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) - { - - } - -} - -@if (_shows?.Count > 0) -{ -
- - Shows - - @if (_shows.Count > 50) - { - See All >> - } -
+ + @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) + { + + } + + } - - @foreach (TelevisionShowCardViewModel card in _shows.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_seasons?.Count > 0) -{ -
- - Seasons - - @if (_seasons.Count > 50) - { - See All >> - } -
+ @if (_shows?.Count > 0) + { +
+ + Shows + + @if (_shows.Count > 50) + { + See All >> + } +
- - @foreach (TelevisionSeasonCardViewModel card in _seasons.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_episodes?.Count > 0) -{ -
- - Episodes - - @if (_episodes.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionShowCardViewModel card in _shows.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (TelevisionEpisodeCardViewModel card in _episodes.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_artists?.Count > 0) -{ -
- - Artists - - @if (_artists.Count > 50) - { - See All >> - } -
+ @if (_seasons?.Count > 0) + { +
+ + Seasons + + @if (_seasons.Count > 50) + { + See All >> + } +
- - @foreach (ArtistCardViewModel card in _artists.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_musicVideos?.Count > 0) -{ -
- - Music Videos - - @if (_musicVideos.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionSeasonCardViewModel card in _seasons.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (MusicVideoCardViewModel card in _musicVideos.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_otherVideos?.Count > 0) -{ -
- - Other Videos - - @if (_otherVideos.Count > 50) - { - See All >> - } -
+ @if (_episodes?.Count > 0) + { +
+ + Episodes + + @if (_episodes.Count > 50) + { + See All >> + } +
- - @foreach (OtherVideoCardViewModel card in _otherVideos.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_songs?.Count > 0) -{ -
- - Songs - - @if (_songs.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionEpisodeCardViewModel card in _episodes.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (SongCardViewModel card in _songs.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} + @if (_artists?.Count > 0) + { +
+ + Artists + + @if (_artists.Count > 50) + { + See All >> + } +
+ + + @foreach (ArtistCardViewModel card in _artists.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_musicVideos?.Count > 0) + { +
+ + Music Videos + + @if (_musicVideos.Count > 50) + { + See All >> + } +
+ + + @foreach (MusicVideoCardViewModel card in _musicVideos.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_otherVideos?.Count > 0) + { +
+ + Other Videos + + @if (_otherVideos.Count > 50) + { + See All >> + } +
+ + + @foreach (OtherVideoCardViewModel card in _otherVideos.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_songs?.Count > 0) + { +
+ + Songs + + @if (_songs.Count > 50) + { + See All >> + } +
+ + + @foreach (SongCardViewModel card in _songs.Cards.OrderBy(s => s.SortTitle)) + { + + } + + }
@code { diff --git a/ErsatzTV/Pages/Settings.razor b/ErsatzTV/Pages/Settings.razor index 1476c0475..729e2dd06 100644 --- a/ErsatzTV/Pages/Settings.razor +++ b/ErsatzTV/Pages/Settings.razor @@ -3,10 +3,10 @@ @using ErsatzTV.Application.Filler @using ErsatzTV.Application.HDHR @using ErsatzTV.Application.MediaItems +@using ErsatzTV.Application.Resolutions @using ErsatzTV.Application.Watermarks @using System.Globalization @using ErsatzTV.Application.Configuration -@using ErsatzTV.Application.Resolutions @using ErsatzTV.Core.Domain.Filler @using ErsatzTV.FFmpeg.OutputFormat @using Serilog.Events @@ -17,232 +17,232 @@ @inject IDialogService Dialog - - - - - FFmpeg Settings - - - - - - - - - - - @foreach (FFmpegProfileViewModel profile in _ffmpegProfiles) - { - @profile.Name - } - - - - @foreach (CultureInfo culture in _availableCultures) - { - @culture.EnglishName - } - - - - - - (none) - @foreach (WatermarkViewModel watermark in _watermarks) - { - @watermark.Name - } - - - (none) - @foreach (FillerPresetViewModel fillerPreset in _fillerPresets) - { - @fillerPreset.Name - } - - - - - - - - - - - - MPEG-TS - MP4 - MKV - - - - - Save Settings - - - - - - - General Settings - - - - - - Debug - Information - Warning - Error - - - - - Save Settings - - - - - - HDHomeRun Settings - - - - - - - - - Save Settings - - - - - - Scanner Settings - - - - - - - - - Save Settings - - - - - - Playout Settings - - - - - - - - - - - - - - Save Settings - - - - - - - - Custom Resolutions - - - - @if (_customResolutions.Any()) + + + + + FFmpeg Settings + + + + + + + + + + + @foreach (FFmpegProfileViewModel profile in _ffmpegProfiles) { - - - - - - - - - @context.Name - -
- - - - -
-
-
-
+ @profile.Name } -
- - - Add Custom Resolution - - -
-
-
+ + + + @foreach (CultureInfo culture in _availableCultures) + { + @culture.EnglishName + } + + + + + + (none) + @foreach (WatermarkViewModel watermark in _watermarks) + { + @watermark.Name + } + + + (none) + @foreach (FillerPresetViewModel fillerPreset in _fillerPresets) + { + @fillerPreset.Name + } + + + + + + + + + + + + MPEG-TS + MP4 + MKV + + + + + Save Settings + + + + + + + General Settings + + + + + + Debug + Information + Warning + Error + + + + + Save Settings + + + + + + HDHomeRun Settings + + + + + + + + + Save Settings + + + + + + Scanner Settings + + + + + + + + + Save Settings + + + + + + Playout Settings + + + + + + + + + + + + + + Save Settings + + + + + + + + Custom Resolutions + + + + @if (_customResolutions.Any()) + { + + + + + + + + + @context.Name + +
+ + + + +
+
+
+
+ } +
+ + + Add Custom Resolution + + +
+
+
@code { @@ -371,11 +371,8 @@ Right: _ => Snackbar.Add("Successfully saved general settings", Severity.Success)); } - private async Task RefreshCustomResolutions() - { - _customResolutions = await Mediator.Send(new GetAllResolutions(), _cts.Token) - .Map(list => list.Filter(r => r.IsCustom).ToList()); - } + private async Task RefreshCustomResolutions() => _customResolutions = await Mediator.Send(new GetAllResolutions(), _cts.Token) + .Map(list => list.Filter(r => r.IsCustom).ToList()); private async Task AddCustomResolution() { @@ -415,4 +412,5 @@ await RefreshCustomResolutions(); } } + } \ No newline at end of file diff --git a/ErsatzTV/Pages/Trash.razor b/ErsatzTV/Pages/Trash.razor index dd63e5a18..3b855b5fb 100644 --- a/ErsatzTV/Pages/Trash.razor +++ b/ErsatzTV/Pages/Trash.razor @@ -89,234 +89,234 @@ -@if (_movies?.Count > 0) -{ -
- - Movies - - @if (_movies.Count > 50) - { - See All >> - } -
+ @if (_movies?.Count > 0) + { +
+ + Movies + + @if (_movies.Count > 50) + { + See All >> + } +
- - @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) - { - - } - -} - -@if (_shows?.Count > 0) -{ -
- - Shows - - @if (_shows.Count > 50) - { - See All >> - } -
+ + @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) + { + + } + + } - - @foreach (TelevisionShowCardViewModel card in _shows.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_seasons?.Count > 0) -{ -
- - Seasons - - @if (_seasons.Count > 50) - { - See All >> - } -
+ @if (_shows?.Count > 0) + { +
+ + Shows + + @if (_shows.Count > 50) + { + See All >> + } +
- - @foreach (TelevisionSeasonCardViewModel card in _seasons.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_episodes?.Count > 0) -{ -
- - Episodes - - @if (_episodes.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionShowCardViewModel card in _shows.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (TelevisionEpisodeCardViewModel card in _episodes.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_artists?.Count > 0) -{ -
- - Artists - - @if (_artists.Count > 50) - { - See All >> - } -
+ @if (_seasons?.Count > 0) + { +
+ + Seasons + + @if (_seasons.Count > 50) + { + See All >> + } +
- - @foreach (ArtistCardViewModel card in _artists.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_musicVideos?.Count > 0) -{ -
- - Music Videos - - @if (_musicVideos.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionSeasonCardViewModel card in _seasons.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (MusicVideoCardViewModel card in _musicVideos.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_otherVideos?.Count > 0) -{ -
- - Other Videos - - @if (_otherVideos.Count > 50) - { - See All >> - } -
+ @if (_episodes?.Count > 0) + { +
+ + Episodes + + @if (_episodes.Count > 50) + { + See All >> + } +
- - @foreach (OtherVideoCardViewModel card in _otherVideos.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} - -@if (_songs?.Count > 0) -{ -
- - Songs - - @if (_songs.Count > 50) - { - See All >> - } -
+ + @foreach (TelevisionEpisodeCardViewModel card in _episodes.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } - - @foreach (SongCardViewModel card in _songs.Cards.OrderBy(s => s.SortTitle)) - { - - } - -} + @if (_artists?.Count > 0) + { +
+ + Artists + + @if (_artists.Count > 50) + { + See All >> + } +
+ + + @foreach (ArtistCardViewModel card in _artists.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_musicVideos?.Count > 0) + { +
+ + Music Videos + + @if (_musicVideos.Count > 50) + { + See All >> + } +
+ + + @foreach (MusicVideoCardViewModel card in _musicVideos.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_otherVideos?.Count > 0) + { +
+ + Other Videos + + @if (_otherVideos.Count > 50) + { + See All >> + } +
+ + + @foreach (OtherVideoCardViewModel card in _otherVideos.Cards.OrderBy(s => s.SortTitle)) + { + + } + + } + + @if (_songs?.Count > 0) + { +
+ + Songs + + @if (_songs.Count > 50) + { + See All >> + } +
+ + + @foreach (SongCardViewModel card in _songs.Cards.OrderBy(s => s.SortTitle)) + { + + } + + }
@code { diff --git a/ErsatzTV/Program.cs b/ErsatzTV/Program.cs index 7b6c9c7d4..424a684e3 100644 --- a/ErsatzTV/Program.cs +++ b/ErsatzTV/Program.cs @@ -43,7 +43,10 @@ public class Program public static async Task Main(string[] args) { - using var _ = new Mutex(true, "Global\\ErsatzTV.Singleton.74360cd8985c4d1fb6bc9e81887206fe", out bool createdNew); + using var _ = new Mutex( + true, + "Global\\ErsatzTV.Singleton.74360cd8985c4d1fb6bc9e81887206fe", + out bool createdNew); if (!createdNew) { Console.WriteLine("Another instance of ErsatztTV is already running."); diff --git a/ErsatzTV/Services/EmbyService.cs b/ErsatzTV/Services/EmbyService.cs index 62824b728..c04d8ad0f 100644 --- a/ErsatzTV/Services/EmbyService.cs +++ b/ErsatzTV/Services/EmbyService.cs @@ -30,7 +30,7 @@ public class EmbyService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + await _systemStartup.WaitForDatabase(cancellationToken); if (cancellationToken.IsCancellationRequested) { diff --git a/ErsatzTV/Services/FFmpegWorkerService.cs b/ErsatzTV/Services/FFmpegWorkerService.cs index 89a6b99bd..78ea2b2f2 100644 --- a/ErsatzTV/Services/FFmpegWorkerService.cs +++ b/ErsatzTV/Services/FFmpegWorkerService.cs @@ -28,7 +28,7 @@ public class FFmpegWorkerService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + try { _logger.LogInformation("FFmpeg worker service started"); diff --git a/ErsatzTV/Services/RunOnce/CacheCleanerService.cs b/ErsatzTV/Services/RunOnce/CacheCleanerService.cs index f821586c3..d338b51c4 100644 --- a/ErsatzTV/Services/RunOnce/CacheCleanerService.cs +++ b/ErsatzTV/Services/RunOnce/CacheCleanerService.cs @@ -31,7 +31,7 @@ public class CacheCleanerService : BackgroundService { return; } - + using IServiceScope scope = _serviceScopeFactory.CreateScope(); await using TvContext dbContext = scope.ServiceProvider.GetRequiredService(); ILocalFileSystem localFileSystem = scope.ServiceProvider.GetRequiredService(); diff --git a/ErsatzTV/Services/RunOnce/DatabaseMigratorService.cs b/ErsatzTV/Services/RunOnce/DatabaseMigratorService.cs index 640db1b6b..8d5a6f45f 100644 --- a/ErsatzTV/Services/RunOnce/DatabaseMigratorService.cs +++ b/ErsatzTV/Services/RunOnce/DatabaseMigratorService.cs @@ -23,7 +23,7 @@ public class DatabaseMigratorService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + _logger.LogInformation("Applying database migrations"); using IServiceScope scope = _serviceScopeFactory.CreateScope(); diff --git a/ErsatzTV/Services/ScannerService.cs b/ErsatzTV/Services/ScannerService.cs index 53ee2b3ff..9e99867a6 100644 --- a/ErsatzTV/Services/ScannerService.cs +++ b/ErsatzTV/Services/ScannerService.cs @@ -31,7 +31,7 @@ public class ScannerService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + try { _logger.LogInformation("Scanner service started"); diff --git a/ErsatzTV/Services/SchedulerService.cs b/ErsatzTV/Services/SchedulerService.cs index 9c8297d48..739d4f3ab 100644 --- a/ErsatzTV/Services/SchedulerService.cs +++ b/ErsatzTV/Services/SchedulerService.cs @@ -21,10 +21,10 @@ namespace ErsatzTV.Services; public class SchedulerService : BackgroundService { private readonly IEntityLocker _entityLocker; - private readonly SystemStartup _systemStartup; private readonly ILogger _logger; private readonly ChannelWriter _scannerWorkerChannel; private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly SystemStartup _systemStartup; private readonly ChannelWriter _workerChannel; public SchedulerService( @@ -46,7 +46,7 @@ public class SchedulerService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + await _systemStartup.WaitForSearchIndex(cancellationToken); if (cancellationToken.IsCancellationRequested) { diff --git a/ErsatzTV/Services/SearchIndexService.cs b/ErsatzTV/Services/SearchIndexService.cs index cecc6c23f..12c143939 100644 --- a/ErsatzTV/Services/SearchIndexService.cs +++ b/ErsatzTV/Services/SearchIndexService.cs @@ -25,7 +25,7 @@ public class SearchIndexService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + try { _logger.LogInformation("Search index worker service started"); diff --git a/ErsatzTV/Services/WorkerService.cs b/ErsatzTV/Services/WorkerService.cs index 37189d54d..88c3b0703 100644 --- a/ErsatzTV/Services/WorkerService.cs +++ b/ErsatzTV/Services/WorkerService.cs @@ -30,7 +30,7 @@ public class WorkerService : BackgroundService protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); - + try { _logger.LogInformation("Worker service started"); diff --git a/ErsatzTV/Shared/AddCustomResolutionDialog.razor b/ErsatzTV/Shared/AddCustomResolutionDialog.razor index ee3c7a681..5cded486c 100644 --- a/ErsatzTV/Shared/AddCustomResolutionDialog.razor +++ b/ErsatzTV/Shared/AddCustomResolutionDialog.razor @@ -25,19 +25,16 @@ private readonly ResolutionEditViewModel _model = new(); - private void Submit() - { - // if (!CanSubmit()) - // { - // return; - // } - + private void Submit() => + // if (!CanSubmit()) + // { + // return; + // } MudDialog.Close(DialogResult.Ok(_model)); - } private void Cancel(MouseEventArgs e) { - // this is gross, but [enter] seems to sometimes trigger cancel instead of submit + // this is gross, but [enter] seems to sometimes trigger cancel instead of submit if (e.Detail == 0) { Submit(); diff --git a/ErsatzTV/Shared/MainLayout.razor b/ErsatzTV/Shared/MainLayout.razor index 86bf541d2..a980e6b46 100644 --- a/ErsatzTV/Shared/MainLayout.razor +++ b/ErsatzTV/Shared/MainLayout.razor @@ -204,10 +204,7 @@ } } - private async void OnStartupProgress(object sender, EventArgs e) - { - await InvokeAsync(StateHasChanged); - } + private async void OnStartupProgress(object sender, EventArgs e) => await InvokeAsync(StateHasChanged); protected override async Task OnParametersSetAsync() { diff --git a/ErsatzTV/ViewModels/ProgramScheduleItemEditViewModel.cs b/ErsatzTV/ViewModels/ProgramScheduleItemEditViewModel.cs index aed7f2074..76ea2506f 100644 --- a/ErsatzTV/ViewModels/ProgramScheduleItemEditViewModel.cs +++ b/ErsatzTV/ViewModels/ProgramScheduleItemEditViewModel.cs @@ -12,8 +12,8 @@ namespace ErsatzTV.ViewModels; public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged { private ProgramScheduleItemCollectionType _collectionType; - private int? _multipleCount; private int? _discardToFillAttempts; + private int? _multipleCount; private TimeSpan? _playoutDuration; private TimeSpan? _startTime; @@ -97,12 +97,13 @@ public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged } public TailMode TailMode { get; set; } - + public int? DiscardToFillAttempts { get => PlayoutMode == PlayoutMode.Duration ? _discardToFillAttempts ?? 0 : null; set => _discardToFillAttempts = value; } + public string CustomTitle { get; set; } public GuideMode GuideMode { get; set; }