Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

151 lines
6.2 KiB

using System.Diagnostics.CodeAnalysis;
using ErsatzTV.Application.Scheduling;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Domain.Scheduling;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Interfaces.Scheduling;
using ErsatzTV.Core.Scheduling;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.MediaCollections;
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
public class PreviewPlaylistPlayoutHandler(
IDbContextFactory<TvContext> dbContextFactory,
IMediaCollectionRepository mediaCollectionRepository,
IPlayoutBuilder playoutBuilder)
: IRequestHandler<PreviewPlaylistPlayout, Either<BaseError, List<PlayoutItemPreviewViewModel>>>
{
public async Task<Either<BaseError, List<PlayoutItemPreviewViewModel>>> Handle(
PreviewPlaylistPlayout request,
CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
var playout = new Playout
{
Channel = new Channel(Guid.NewGuid())
{
Number = "1",
Name = "Playlist Preview"
},
Items = [],
ScheduleKind = PlayoutScheduleKind.Classic,
PlayoutHistory = [],
ProgramSchedule = new ProgramSchedule
{
Items = [MapToScheduleItem(request)]
},
ProgramScheduleAnchors = [],
ProgramScheduleAlternates = [],
FillGroupIndices = [],
Templates = []
};
var referenceData = new PlayoutReferenceData(
playout.Channel,
Option<Deco>.None,
playout.Items,
playout.Templates.ToList(),
playout.ProgramSchedule,
playout.ProgramScheduleAlternates.ToList(),
playout.PlayoutHistory.ToList(),
TimeSpan.Zero);
// TODO: make an explicit method to preview, this is ugly
playoutBuilder.TrimStart = false;
playoutBuilder.DebugPlaylist = playout.ProgramSchedule.Items[0].Playlist;
Either<BaseError, PlayoutBuildResult> buildResult = await playoutBuilder.Build(
DateTimeOffset.Now,
playout,
referenceData,
PlayoutBuildMode.Reset,
cancellationToken);
return await buildResult.MatchAsync<Either<BaseError, List<PlayoutItemPreviewViewModel>>>(
async result =>
{
var maxItems = 0;
Dictionary<PlaylistItem, List<MediaItem>> map =
await mediaCollectionRepository.GetPlaylistItemMap(
playout.ProgramSchedule.Items[0].Playlist,
cancellationToken);
foreach (PlaylistItem item in playout.ProgramSchedule.Items[0].Playlist.Items)
{
if (item.PlayAll)
{
maxItems += map[item].Count;
}
else
{
maxItems += 1;
}
}
// limit preview to once through the playlist
var onceThrough = result.AddedItems.Take(maxItems).ToList();
// load playout item details for title
foreach (PlayoutItem playoutItem in onceThrough)
{
Option<MediaItem> maybeMediaItem = await dbContext.MediaItems
.AsNoTracking()
.Include(mi => (mi as Movie).MovieMetadata)
.Include(mi => (mi as Movie).MediaVersions)
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
.Include(mi => (mi as MusicVideo).MediaVersions)
.Include(mi => (mi as MusicVideo).Artist)
.ThenInclude(mm => mm.ArtistMetadata)
.Include(mi => (mi as Episode).EpisodeMetadata)
.Include(mi => (mi as Episode).MediaVersions)
.Include(mi => (mi as Episode).Season)
.ThenInclude(s => s.SeasonMetadata)
.Include(mi => (mi as Episode).Season.Show)
.ThenInclude(s => s.ShowMetadata)
.Include(mi => (mi as OtherVideo).OtherVideoMetadata)
.Include(mi => (mi as OtherVideo).MediaVersions)
.Include(mi => (mi as Song).SongMetadata)
.Include(mi => (mi as Song).MediaVersions)
.Include(mi => (mi as Image).ImageMetadata)
.Include(mi => (mi as Image).MediaVersions)
.SelectOneAsync(mi => mi.Id, mi => mi.Id == playoutItem.MediaItemId, cancellationToken);
foreach (MediaItem mediaItem in maybeMediaItem)
{
playoutItem.MediaItem = mediaItem;
}
}
return onceThrough.OrderBy(i => i.StartOffset).Map(Scheduling.Mapper.ProjectToViewModel).ToList();
},
error => error);
}
private static ProgramScheduleItemFlood MapToScheduleItem(PreviewPlaylistPlayout request) =>
new()
{
CollectionType = CollectionType.Playlist,
Playlist = new Playlist
{
Items = request.Data.Items.OrderBy(i => i.Index).Map(MapToPlaylistItem).ToList()
},
PlaylistId = request.Data.PlaylistId,
PlaybackOrder = PlaybackOrder.Shuffle
};
private static PlaylistItem MapToPlaylistItem(ReplacePlaylistItem item) =>
new()
{
Index = item.Index,
CollectionType = item.CollectionType,
CollectionId = item.CollectionId,
MediaItemId = item.MediaItemId,
MultiCollectionId = item.MultiCollectionId,
SmartCollectionId = item.SmartCollectionId,
PlaybackOrder = item.PlaybackOrder,
PlayAll = item.PlayAll
};
}