From e45fb677694e1a4de8ec07877e4c42b1b5b734d7 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Tue, 23 Nov 2021 11:44:39 -0600 Subject: [PATCH] bug fixes (#493) * don't align audio when playing songs * fix grouping duration items in epg --- CHANGELOG.md | 1 + .../PlayoutModeSchedulerDurationTests.cs | 66 +++++++++++++++++++ ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs | 2 +- .../PlayoutModeSchedulerDuration.cs | 14 +++- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2245522c4..ad70ea032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Properly fix database incompatibility introduced with v0.2.4-alpha and partially fixed with v0.2.5-alpha - The proper fix requires rebuilding all playouts, which will happen on startup after upgrading - Fix local library locking/progress display when adding paths +- Fix grouping duration items in EPG when custom title is configured ### Added - Add *experimental* `Songs` local libraries diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs index 40179d8a9..218596472 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs @@ -76,6 +76,72 @@ namespace ErsatzTV.Core.Tests.Scheduling playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); } + [Test] + public void Should_Fill_Exact_Duration_CustomTitle() + { + Collection collectionOne = TwoItemCollection(1, 2, TimeSpan.FromHours(1)); + + var scheduleItem = new ProgramScheduleItemDuration + { + Id = 1, + Index = 1, + Collection = collectionOne, + CollectionId = collectionOne.Id, + StartTime = null, + PlayoutDuration = TimeSpan.FromHours(3), + TailMode = TailMode.None, + PlaybackOrder = PlaybackOrder.Chronological, + CustomTitle = "Custom Title" + }; + + var enumerator = new ChronologicalMediaCollectionEnumerator( + collectionOne.MediaItems, + new CollectionEnumeratorState()); + + var scheduler = new PlayoutModeSchedulerDuration(new Mock().Object); + (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( + StartState, + CollectionEnumerators(scheduleItem, enumerator), + scheduleItem, + NextScheduleItem, + HardStop); + + playoutBuilderState.CurrentTime.Should().Be(StartState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.Should().Be(2); + playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); + playoutBuilderState.InFlood.Should().BeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); + playoutBuilderState.InDurationFiller.Should().BeFalse(); + playoutBuilderState.ScheduleItemIndex.Should().Be(1); + + enumerator.State.Index.Should().Be(1); + + playoutItems.Count.Should().Be(3); + + playoutItems[0].MediaItemId.Should().Be(1); + playoutItems[0].StartOffset.Should().Be(StartState.CurrentTime); + playoutItems[0].GuideGroup.Should().Be(1); + playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); + playoutItems[0].CustomTitle.Should().Be("Custom Title"); + + playoutItems[1].MediaItemId.Should().Be(2); + playoutItems[1].StartOffset.Should().Be(StartState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.Should().Be(1); + playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); + playoutItems[1].CustomTitle.Should().Be("Custom Title"); + + playoutItems[2].MediaItemId.Should().Be(1); + playoutItems[2].StartOffset.Should().Be(StartState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.Should().Be(1); + playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); + playoutItems[2].CustomTitle.Should().Be("Custom Title"); + } + [Test] public void Should_Not_Have_Gap_Duration_Tail_Mode_None() { diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs index 43fe30c26..04fb0bf39 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs @@ -87,7 +87,7 @@ namespace ErsatzTV.Core.FFmpeg videoStream.PixelFormat) .WithWatermark(watermarkOptions, channel.FFmpegProfile.Resolution) .WithVideoTrackTimeScale(playbackSettings.VideoTrackTimeScale) - .WithAlignedAudio(playbackSettings.AudioDuration) + .WithAlignedAudio(videoPath == audioPath ? playbackSettings.AudioDuration : Option.None) .WithNormalizeLoudness(playbackSettings.NormalizeLoudness); playbackSettings.ScaledSize.Match( diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs index 2264ee84a..9a28b7d18 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs @@ -76,7 +76,8 @@ namespace ErsatzTV.Core.Scheduling GuideGroup = nextState.NextGuideGroup, FillerKind = scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.Tail - : FillerKind.None + : FillerKind.None, + CustomTitle = scheduleItem.CustomTitle }; durationUntil.Do(du => playoutItem.GuideFinish = du.UtcDateTime); @@ -99,7 +100,11 @@ namespace ErsatzTV.Core.Scheduling nextState = nextState with { CurrentTime = itemEndTimeWithFiller, - NextGuideGroup = nextState.IncrementGuideGroup + + // only bump guide group if we don't have a custom title + NextGuideGroup = string.IsNullOrWhiteSpace(scheduleItem.CustomTitle) + ? nextState.IncrementGuideGroup + : nextState.NextGuideGroup }; contentEnumerator.MoveNext(); @@ -133,7 +138,10 @@ namespace ErsatzTV.Core.Scheduling }; } - nextState = nextState with { NextGuideGroup = nextState.DecrementGuideGroup }; + if (playoutItems.Select(pi => pi.GuideGroup).Distinct().Count() != 1) + { + nextState = nextState with { NextGuideGroup = nextState.DecrementGuideGroup }; + } foreach (DateTimeOffset nextItemStart in durationUntil) {