diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml
index 88f0791f7..da918bd50 100644
--- a/.github/workflows/artifacts.yml
+++ b/.github/workflows/artifacts.yml
@@ -203,7 +203,7 @@ jobs:
- name: Install dependencies
run: dotnet restore -r "${{ matrix.target }}"
- - uses: suisei-cn/actions-download-file@v1
+ - uses: suisei-cn/actions-download-file@v1.3.0
if: ${{ matrix.kind == 'windows' }}
id: downloadffmpeg
name: Download ffmpeg
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79a597553..0e719265d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix fallback filler looping
- Fix bug where some libraries would never scan
- Fix filler ordering so post-roll is properly scheduled after padded mid-roll
+- Fix pre/post-roll filler padding when used with mid-roll
+ - This caused overlapping schedule items, fallback filler that was too long, etc.
### Changed
- Merge generated `Other Video` folder tags with tags from sidecar NFO
diff --git a/ErsatzTV.Application/ErsatzTV.Application.csproj b/ErsatzTV.Application/ErsatzTV.Application.csproj
index 0835a37aa..234ab9198 100644
--- a/ErsatzTV.Application/ErsatzTV.Application.csproj
+++ b/ErsatzTV.Application/ErsatzTV.Application.csproj
@@ -12,7 +12,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
index 05ee1dcbf..9a1badcf6 100644
--- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
+++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
@@ -10,14 +10,14 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs
index f402dc10e..12bbc7703 100644
--- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs
+++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs
@@ -460,6 +460,110 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
playoutItems[4].MediaItemId.Should().Be(5);
playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55));
}
+
+ [Test]
+ public void Should_Schedule_Padded_Post_Roll_After_Mid_Roll_Count()
+ {
+ // content 45 min, mid roll 5 min, post roll pad to 60
+ // content + mid = 50 min, post roll will add two 5 min items
+ // content + mid + post = 60 min
+
+ Collection collectionOne = TwoItemCollection(1, 2, TimeSpan.FromMinutes(45));
+ Collection collectionTwo = TwoItemCollection(3, 4, TimeSpan.FromMinutes(5));
+ Collection collectionThree = TwoItemCollection(5, 6, TimeSpan.FromMinutes(5));
+
+ var scheduleItem = new ProgramScheduleItemOne
+ {
+ Id = 1,
+ Index = 1,
+ Collection = collectionOne,
+ CollectionId = collectionOne.Id,
+ StartTime = null,
+ PlaybackOrder = PlaybackOrder.Chronological,
+ TailFiller = null,
+ FallbackFiller = null,
+ MidRollFiller = new FillerPreset
+ {
+ FillerKind = FillerKind.MidRoll,
+ FillerMode = FillerMode.Count,
+ Count = 1,
+ CollectionId = 2,
+ Collection = collectionTwo
+ },
+ PostRollFiller = new FillerPreset
+ {
+ FillerKind = FillerKind.PostRoll,
+ FillerMode = FillerMode.Pad,
+ PadToNearestMinute = 60,
+ CollectionId = 3,
+ Collection = collectionThree
+ }
+ };
+
+ var scheduleItemsEnumerator = new OrderedScheduleItemsEnumerator(
+ new List { scheduleItem },
+ new CollectionEnumeratorState());
+
+ var enumerator = new ChronologicalMediaCollectionEnumerator(
+ collectionOne.MediaItems,
+ new CollectionEnumeratorState());
+
+ var midRollFillerEnumerator = new ChronologicalMediaCollectionEnumerator(
+ collectionTwo.MediaItems,
+ new CollectionEnumeratorState());
+
+ var postRollFillerEnumerator = new ChronologicalMediaCollectionEnumerator(
+ collectionThree.MediaItems,
+ new CollectionEnumeratorState());
+
+ PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
+
+ Dictionary enumerators = CollectionEnumerators(
+ scheduleItem,
+ enumerator);
+
+ enumerators.Add(CollectionKey.ForFillerPreset(scheduleItem.MidRollFiller), midRollFillerEnumerator);
+ enumerators.Add(CollectionKey.ForFillerPreset(scheduleItem.PostRollFiller), postRollFillerEnumerator);
+
+ List playoutItems = Scheduler()
+ .AddFiller(
+ startState,
+ enumerators,
+ scheduleItem,
+ new PlayoutItem
+ {
+ MediaItemId = 1,
+ Start = startState.CurrentTime.UtcDateTime,
+ Finish = startState.CurrentTime.AddHours(1).UtcDateTime
+ },
+ new List
+ {
+ new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) },
+ new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) }
+ });
+
+ playoutItems.Count.Should().Be(5);
+
+ // content chapter 1
+ playoutItems[0].MediaItemId.Should().Be(1);
+ playoutItems[0].StartOffset.Should().Be(startState.CurrentTime);
+
+ // mid-roll 1
+ playoutItems[1].MediaItemId.Should().Be(3);
+ playoutItems[1].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(6));
+
+ // content chapter 2
+ playoutItems[2].MediaItemId.Should().Be(1);
+ playoutItems[2].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(11));
+
+ // post-roll 1
+ playoutItems[3].MediaItemId.Should().Be(5);
+ playoutItems[3].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(50));
+
+ // post-roll 2
+ playoutItems[4].MediaItemId.Should().Be(6);
+ playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55));
+ }
}
[TestFixture]
diff --git a/ErsatzTV.Core/ErsatzTV.Core.csproj b/ErsatzTV.Core/ErsatzTV.Core.csproj
index a93e3b433..86cdf35c5 100644
--- a/ErsatzTV.Core/ErsatzTV.Core.csproj
+++ b/ErsatzTV.Core/ErsatzTV.Core.csproj
@@ -10,15 +10,15 @@
-
-
+
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
index a3b8ee1a3..3e1e50f58 100644
--- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
+++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
@@ -461,10 +461,14 @@ public abstract class PlayoutModeSchedulerBase : IPlayoutModeScheduler whe
foreach (FillerPreset padFiller in Optional(
allFiller.FirstOrDefault(f => f.FillerMode == FillerMode.Pad && f.PadToNearestMinute.HasValue)))
{
- var totalDuration =
- TimeSpan.FromMilliseconds(
- result.Sum(pi => (pi.Finish - pi.Start).TotalMilliseconds) +
+ var totalDuration = TimeSpan.FromMilliseconds(result.Sum(pi => (pi.Finish - pi.Start).TotalMilliseconds));
+
+ // add primary content to totalDuration only if it hasn't already been added
+ if (result.All(pi => pi.MediaItemId != playoutItem.MediaItemId))
+ {
+ totalDuration += TimeSpan.FromMilliseconds(
effectiveChapters.Sum(c => (c.EndTime - c.StartTime).TotalMilliseconds));
+ }
int currentMinute = (playoutItem.StartOffset + totalDuration).Minute;
// ReSharper disable once PossibleInvalidOperationException
diff --git a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj
index a759d92af..5c8e7e140 100644
--- a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj
+++ b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
index 2efb8c78d..e2eb08145 100644
--- a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
+++ b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
@@ -21,14 +21,14 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj
index 439348d57..ed1174309 100644
--- a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj
+++ b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj b/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj
index 55ed59508..b8dad3f40 100644
--- a/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj
+++ b/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/ErsatzTV/ErsatzTV.csproj b/ErsatzTV/ErsatzTV.csproj
index 9617f4c2e..1f32155b9 100644
--- a/ErsatzTV/ErsatzTV.csproj
+++ b/ErsatzTV/ErsatzTV.csproj
@@ -57,7 +57,7 @@
-
+
@@ -68,7 +68,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive