diff --git a/CHANGELOG.md b/CHANGELOG.md index b517442b..f46cd2f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - All NVIDIA docker users - Windows NVIDIA users who have set the `ETV_DISABLE_VULKAN` env var - Fix audio sync issue with QSV acceleration -- YAML playout: fix history for marathon content +- YAML playout: fix history for marathon and playlist content - This allows playouts to be extended correctly, instead of always resetting to the earliest item in each group ## [25.2.0] - 2025-06-24 diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs index 0c59cd3a..fc03871c 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs @@ -112,7 +112,7 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor // playlist is a special case that needs to be handled on its own if (content is YamlPlayoutContentPlaylistItem playlist) { - if (!string.IsNullOrWhiteSpace(playlist.Order)) + if (!string.IsNullOrWhiteSpace(playlist.Order) && !string.Equals(playlist.Order, "none", StringComparison.OrdinalIgnoreCase)) { logger.LogWarning( "Ignoring playback order {Order} for playlist {Playlist}", @@ -123,12 +123,12 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor Dictionary> itemMap = await mediaCollectionRepository.GetPlaylistItemMap(playlist.PlaylistGroup, playlist.Playlist); - // foreach ((PlaylistItem playlistItem, List mediaItems) in itemMap) - // { - // _playlistMediaItems.Add( - // new PlaylistKey(contentKey, CollectionKey.ForPlaylistItem(playlistItem)), - // mediaItems); - // } + foreach ((PlaylistItem playlistItem, List mediaItems) in itemMap) + { + _playlistMediaItems.Add( + new PlaylistKey(contentKey, CollectionKey.ForPlaylistItem(playlistItem)), + mediaItems); + } return await PlaylistEnumerator.Create( mediaCollectionRepository, diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutApplyHistoryHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutApplyHistoryHandler.cs index 5c2aa9f3..eddf663d 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutApplyHistoryHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutApplyHistoryHandler.cs @@ -53,7 +53,7 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache) foreach (IMediaCollectionEnumerator enumerator in maybeEnumerator) { - if (contentItem is YamlPlayoutContentMarathonItem marathonItem && enumerator is PlaylistEnumerator playlistEnumerator) + if (enumerator is PlaylistEnumerator playlistEnumerator) { Option maybePrimaryHistory = maybeHistory .Filter(h => string.IsNullOrWhiteSpace(h.ChildKey)) @@ -61,16 +61,19 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache) foreach (PlayoutHistory primaryHistory in maybePrimaryHistory) { - bool hasSetEnumeratorIndex = false; - - if (!Enum.TryParse(marathonItem.ItemOrder, true, out PlaybackOrder itemPlaybackOrder)) - { - itemPlaybackOrder = PlaybackOrder.None; - } + var hasSetEnumeratorIndex = false; var childEnumeratorKeys = playlistEnumerator.ChildEnumerators.Map(x => x.CollectionKey).ToList(); foreach ((IMediaCollectionEnumerator childEnumerator, CollectionKey collectionKey) in playlistEnumerator.ChildEnumerators) { + PlaybackOrder itemPlaybackOrder = childEnumerator switch + { + ChronologicalMediaCollectionEnumerator => PlaybackOrder.Chronological, + RandomizedMediaCollectionEnumerator => PlaybackOrder.Random, + ShuffledMediaCollectionEnumerator => PlaybackOrder.Shuffle, + _ => PlaybackOrder.None + }; + Option maybeApplicableHistory = maybeHistory .Filter(h => h.ChildKey == HistoryDetails.KeyForCollectionKey(collectionKey)) .HeadOrNone(); @@ -99,8 +102,8 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache) collectionItems, h.Details, childEnumerator, - playbackOrder, - !h.IsCurrentChild); + itemPlaybackOrder, + true); } if (h.IsCurrentChild) @@ -117,6 +120,10 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache) // falling back to enumerator based on index playlistEnumerator.SetEnumeratorIndex(primaryHistory.Index); } + + // only move next at the end, because that may also move + // the enumerator index + playlistEnumerator.MoveNext(); } } else diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs index 84ad0baf..bf9f3790 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs @@ -75,7 +75,7 @@ public abstract class YamlPlayoutContentHandler(EnumeratorCache enumeratorCache) string historyKey = HistoryDetails.KeyForYamlContent(contentItem); - if (contentItem is YamlPlayoutContentMarathonItem && enumerator is PlaylistEnumerator playlistEnumerator) + if (enumerator is PlaylistEnumerator playlistEnumerator) { // create a playout history record var nextHistory = new PlayoutHistory diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentPlaylistItem.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentPlaylistItem.cs index f46ccc2a..a430adfe 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentPlaylistItem.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentPlaylistItem.cs @@ -8,4 +8,10 @@ public class YamlPlayoutContentPlaylistItem : YamlPlayoutContentItem [YamlMember(Alias = "playlist_group", ApplyNamingConventions = false)] public string PlaylistGroup { get; set; } + + public override string Order + { + get => "none"; + set => throw new NotSupportedException(); + } }