diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a820891..0c4f15ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add health check error when invalid VAAPI device and VAAPI driver combination is used in an active ffmpeg profile - This makes it obvious when hardware acceleration will not work as configured - Add button in schedule editor to clone schedule item +- Allow YAML playout sequence definitions to reference other sequences + - Playout builder will behave in unexpected ways if nesting is too deep +- Add `repeat` property to YAML sequence instruction + - This tells the playout builder how many times this sequence should repeat + - Omitting this value is the same as setting it to `1` ### Changed - Start to make UI minimally responsive (functional on smaller screens) diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSequenceInstruction.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSequenceInstruction.cs index 98107505..4d7871a8 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSequenceInstruction.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSequenceInstruction.cs @@ -3,4 +3,5 @@ namespace ErsatzTV.Core.Scheduling.YamlScheduling.Models; public class YamlPlayoutSequenceInstruction : YamlPlayoutInstruction { public string Sequence { get; set; } + public int Repeat { get; set; } } diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs index ca4efc1a..d07329b9 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs @@ -127,7 +127,19 @@ public class YamlPlayoutBuilder( } } - FlattenSequences(context); + int flattenCount = 0; + while (context.Definition.Playout.Any(x => x is YamlPlayoutSequenceInstruction)) + { + if (flattenCount > 10) + { + logger.LogError( + "YAML playout definition contains sequence nesting that is too deep; this introduces undefined behavior"); + break; + } + + FlattenSequences(context); + flattenCount++; + } // handle all playout instructions while (context.CurrentTime < finish) @@ -204,25 +216,31 @@ public class YamlPlayoutBuilder( .Filter(s => s.Key == sequenceInstruction.Sequence) .HeadOrNone() .Map(s => s.Items) - .Flatten(); + .Flatten() + .ToList(); var sequenceGuid = Guid.NewGuid(); + int repeat = sequenceInstruction.Repeat > 0 ? sequenceInstruction.Repeat : 1; - // insert all instructions from the sequence - foreach (YamlPlayoutInstruction i in sequenceInstructions) + for (var r = 0; r < repeat; r++) { - // used for shuffling - i.SequenceKey = sequenceInstruction.Sequence; - i.SequenceGuid = sequenceGuid; - - // copy custom title - if (!string.IsNullOrWhiteSpace(sequenceInstruction.CustomTitle)) + // insert all instructions from the sequence + foreach (YamlPlayoutInstruction i in sequenceInstructions) { - i.CustomTitle = sequenceInstruction.CustomTitle; - } + // used for shuffling + i.SequenceKey = sequenceInstruction.Sequence; + i.SequenceGuid = sequenceGuid; + + // copy custom title + if (!string.IsNullOrWhiteSpace(sequenceInstruction.CustomTitle)) + { + i.CustomTitle = sequenceInstruction.CustomTitle; + } - context.Definition.Playout.Add(i); + context.Definition.Playout.Add(i); + } } + break; default: context.Definition.Playout.Add(instruction);