diff --git a/CHANGELOG.md b/CHANGELOG.md index 63f19bf1e..799ad353e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix error loading path replacements when using MySql - Fix tray icon shortcut to open logs folder on Windows +- Unlock playout when playout build fails ### Changed - Upgrade from .NET 7 to .NET 8 diff --git a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs index d4fdf432b..ba2ae1529 100644 --- a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs +++ b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs @@ -70,8 +70,6 @@ public class BuildPlayoutHandler : IRequestHandler maybeChannelNumber = await dbContext.Connection .QuerySingleOrDefaultAsync( @"select C.Number from Channel C @@ -103,6 +101,10 @@ public class BuildPlayoutHandler : IRequestHandler> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator), @@ -119,14 +119,14 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionOne.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator), @@ -201,15 +201,15 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionTwo.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2), @@ -300,15 +300,15 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionTwo.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionTwo.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionTwo.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.FallbackFiller, enumerator2), @@ -389,15 +389,15 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionTwo.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2), @@ -498,16 +498,16 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionThree.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionThree.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionThree.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators( @@ -620,16 +620,16 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase collectionThree.MediaItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems }, - { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionThree.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.TailFiller), collectionTwo.MediaItems.Count }, + { CollectionKey.ForFillerPreset(scheduleItem.FallbackFiller), collectionThree.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators( @@ -708,14 +708,14 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase sortedScheduleItems, new CollectionEnumeratorState()); - var collectionMediaItems = new Dictionary> + var collectionItemCount = new Dictionary { - { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems } + { CollectionKey.ForScheduleItem(scheduleItem), collectionOne.MediaItems.Count } }.ToMap(); PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); - var scheduler = new PlayoutModeSchedulerMultiple(collectionMediaItems, Substitute.For()); + var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For()); (PlayoutBuilderState playoutBuilderState, List playoutItems) = scheduler.Schedule( startState, CollectionEnumerators(scheduleItem, enumerator), diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index 62f225140..04c913c1a 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -406,7 +406,27 @@ public class PlayoutBuilder : IPlayoutBuilder : new OrderedScheduleItemsEnumerator(activeSchedule.Items, scheduleItemsEnumeratorState); var collectionEnumerators = new Dictionary(); - + foreach ((CollectionKey collectionKey, List mediaItems) in collectionMediaItems) + { + // use configured playback order for primary collection, shuffle for filler + Option maybeScheduleItem = sortedScheduleItems + .FirstOrDefault(item => CollectionKey.ForScheduleItem(item) == collectionKey); + PlaybackOrder playbackOrder = maybeScheduleItem + .Match(item => item.PlaybackOrder, () => PlaybackOrder.Shuffle); + IMediaCollectionEnumerator enumerator = + await GetMediaCollectionEnumerator( + playout, + activeSchedule, + collectionKey, + mediaItems, + playbackOrder, + randomStartPoint, + cancellationToken); + collectionEnumerators.Add(collectionKey, enumerator); + } + + var collectionItemCount = collectionMediaItems.Map((k, v) => (k, v.Count)).Values.ToDictionary(); + var scheduleItemsFillGroupEnumerators = new Dictionary(); foreach (ProgramScheduleItem scheduleItem in sortedScheduleItems.Where(si => si.FillWithGroupMode is not FillWithGroupMode.None)) { @@ -453,6 +473,9 @@ public class PlayoutBuilder : IPlayoutBuilder cancellationToken); collectionEnumerators.Add(key, enumerator); + + // this makes multiple (0) work - since it needs the number of items in the collection + collectionItemCount.Add(key, fakeCollection.MediaItems.Count); } CollectionEnumeratorState enumeratorState = @@ -476,25 +499,6 @@ public class PlayoutBuilder : IPlayoutBuilder } } } - - foreach ((CollectionKey collectionKey, List mediaItems) in collectionMediaItems) - { - // use configured playback order for primary collection, shuffle for filler - Option maybeScheduleItem = sortedScheduleItems - .FirstOrDefault(item => CollectionKey.ForScheduleItem(item) == collectionKey); - PlaybackOrder playbackOrder = maybeScheduleItem - .Match(item => item.PlaybackOrder, () => PlaybackOrder.Shuffle); - IMediaCollectionEnumerator enumerator = - await GetMediaCollectionEnumerator( - playout, - activeSchedule, - collectionKey, - mediaItems, - playbackOrder, - randomStartPoint, - cancellationToken); - collectionEnumerators.Add(collectionKey, enumerator); - } // find start anchor PlayoutAnchor startAnchor = FindStartAnchor(playout, playoutStart, scheduleItemsEnumerator); @@ -537,7 +541,7 @@ public class PlayoutBuilder : IPlayoutBuilder currentTime); var schedulerOne = new PlayoutModeSchedulerOne(_logger); - var schedulerMultiple = new PlayoutModeSchedulerMultiple(collectionMediaItems, _logger); + var schedulerMultiple = new PlayoutModeSchedulerMultiple(collectionItemCount.ToMap(), _logger); var schedulerDuration = new PlayoutModeSchedulerDuration(_logger); var schedulerFlood = new PlayoutModeSchedulerFlood(_logger); diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs index 680d4c11e..8240b02b4 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs @@ -8,11 +8,13 @@ namespace ErsatzTV.Core.Scheduling; public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase { - private readonly Map> _collectionMediaItems; + private readonly Map _collectionItemCount; - public PlayoutModeSchedulerMultiple(Map> collectionMediaItems, ILogger logger) - : base(logger) => - _collectionMediaItems = collectionMediaItems; + public PlayoutModeSchedulerMultiple(Map collectionItemCount, ILogger logger) + : base(logger) + { + _collectionItemCount = collectionItemCount; + } public override Tuple> Schedule( PlayoutBuilderState playoutBuilderState, @@ -40,7 +42,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase