filler rework (#449)

* add chapter statistics and new filler options

* refactor playout builder

* more refactor prep for filler

* rewrite schedulers

* refactor collectionkey

* add tail filler kind

* migrate tail filler to filler preset

* optionally show filler

* fix playout detail row count

* remove duration tail filler options

* implement tail and fallback in flood scheduler

* implement tail and fallback in one scheduler

* implement tail and fallback in multiple scheduler

* implement looping fallback filler

* more duration tests

* start to add post-roll filler to flood

* rework playoutitem filler tagging

* rework scheduler logging

* calculate whether configured filler will fit

* implement pre-roll and post-roll duration and count filler

* improve duration filler calculation

* add minutes to search index

* update channel guide to work with new filler

* add mid-roll filler

* don't clone enumerators for filler calculations

* support pre-roll and post-roll pad filler

* implement mid-roll pad filler

* allow clearing filler selections in schedule editor

* fix tests

* filler config validation

* use consistent time zone for tests
This commit is contained in:
Jason Dove
2021-10-21 20:23:14 -05:00
committed by GitHub
parent f4a63a1a1a
commit 6d147de2f3
133 changed files with 54673 additions and 990 deletions
+17 -20
View File
@@ -8,13 +8,13 @@ namespace ErsatzTV.Application.Playouts
{
internal static PlayoutItemViewModel ProjectToViewModel(PlayoutItem playoutItem) =>
new(
GetDisplayTitle(playoutItem.MediaItem),
GetDisplayTitle(playoutItem),
playoutItem.StartOffset,
GetDisplayDuration(playoutItem.MediaItem));
GetDisplayDuration(playoutItem.FinishOffset - playoutItem.StartOffset));
private static string GetDisplayTitle(MediaItem mediaItem)
private static string GetDisplayTitle(PlayoutItem playoutItem)
{
switch (mediaItem)
switch (playoutItem.MediaItem)
{
case Episode e:
string showTitle = e.Season.Show.ShowMetadata.HeadOrNone()
@@ -28,6 +28,11 @@ namespace ErsatzTV.Application.Playouts
var numbersString = $"e{string.Join('e', episodeNumbers.Map(n => $"{n:00}"))}";
var titlesString = $"{string.Join('/', episodeTitles)}";
if (!string.IsNullOrWhiteSpace(playoutItem.ChapterTitle))
{
titlesString += $" ({playoutItem.ChapterTitle})";
}
return $"{showTitle}s{e.Season.SeasonNumber:00}{numbersString} - {titlesString}";
case Movie m:
return m.MovieMetadata.HeadOrNone().Map(mm => mm.Title).IfNone("[unknown movie]");
@@ -36,29 +41,21 @@ namespace ErsatzTV.Application.Playouts
.Map(am => $"{am.Title} - ").IfNone(string.Empty);
return mv.MusicVideoMetadata.HeadOrNone()
.Map(mvm => $"{artistName}{mvm.Title}")
.Map(s => string.IsNullOrWhiteSpace(playoutItem.ChapterTitle) ? s : $"{s} ({playoutItem.ChapterTitle})")
.IfNone("[unknown music video]");
case OtherVideo ov:
return ov.OtherVideoMetadata.HeadOrNone().Map(ovm => ovm.Title ?? string.Empty)
return ov.OtherVideoMetadata.HeadOrNone()
.Map(ovm => ovm.Title ?? string.Empty)
.Map(s => string.IsNullOrWhiteSpace(playoutItem.ChapterTitle) ? s : $"{s} ({playoutItem.ChapterTitle})")
.IfNone("[unknown video]");
default:
return string.Empty;
}
}
private static string GetDisplayDuration(MediaItem mediaItem)
{
MediaVersion version = mediaItem switch
{
Movie m => m.MediaVersions.Head(),
Episode e => e.MediaVersions.Head(),
MusicVideo mv => mv.MediaVersions.Head(),
OtherVideo ov => ov.MediaVersions.Head(),
_ => throw new ArgumentOutOfRangeException(nameof(mediaItem))
};
return string.Format(
version.Duration.TotalHours >= 1 ? @"{0:h\:mm\:ss}" : @"{0:mm\:ss}",
version.Duration);
}
private static string GetDisplayDuration(TimeSpan duration) =>
string.Format(
duration.TotalHours >= 1 ? @"{0:h\:mm\:ss}" : @"{0:mm\:ss}",
duration);
}
}