add rerun collection type (#2421)
* rename collection type * split collections into separate pages * add rerun collection types, migration, editor * add rerun to classic schedule items * rerun plumbing in classic playout builder * start to implement rerun enumerator * add scheduledAt to enumerator movenext * maintain rerun history in db * fix shuffle * fix rerun allowed playback orders * fix updating rerun collections * update changelog; fix editing * update changelog
This commit is contained in:
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- Add new collection type `Rerun Collection`
|
||||||
|
- This collection type will show up as *two* collection types in classic schedules
|
||||||
|
- `Rerun (First Run)`
|
||||||
|
- `Rerun (Rerun)`
|
||||||
|
- The playback order for each of these collection types can be set on the rerun collection itself
|
||||||
|
- e.g. `Season, Episode` order for first run, `Shuffle` for rerun
|
||||||
|
- When a first run item is added to a playout, it will immediately be made available in the rerun collection
|
||||||
|
- Rerun history is currently scoped to the playout, and only supported in classic schedules
|
||||||
|
- This means resetting the playout will reset the rerun history
|
||||||
|
- Items will still be scheduled from the rerun collection if it is used before the first run collection
|
||||||
|
- Otherwise, the rerun collection would be considered "empty" which prevents the playout build altogether
|
||||||
|
|
||||||
## [25.6.0] - 2025-09-14
|
## [25.6.0] - 2025-09-14
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public record CreateFillerPreset(
|
|||||||
int? Count,
|
int? Count,
|
||||||
int? PadToNearestMinute,
|
int? PadToNearestMinute,
|
||||||
bool AllowWatermarks,
|
bool AllowWatermarks,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public record UpdateFillerPreset(
|
|||||||
int? Count,
|
int? Count,
|
||||||
int? PadToNearestMinute,
|
int? PadToNearestMinute,
|
||||||
bool AllowWatermarks,
|
bool AllowWatermarks,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public record FillerPresetViewModel(
|
|||||||
int? Count,
|
int? Count,
|
||||||
int? PadToNearestMinute,
|
int? PadToNearestMinute,
|
||||||
bool AllowWatermarks,
|
bool AllowWatermarks,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class AddEpisodeToPlaylistHandler(IDbContextFactory<TvContext> dbContextF
|
|||||||
var playlistItem = new PlaylistItem
|
var playlistItem = new PlaylistItem
|
||||||
{
|
{
|
||||||
Index = index,
|
Index = index,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Episode,
|
CollectionType = CollectionType.Episode,
|
||||||
MediaItemId = parameters.Episode.Id,
|
MediaItemId = parameters.Episode.Id,
|
||||||
PlaybackOrder = PlaybackOrder.Shuffle,
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
IncludeInProgramGuide = true
|
IncludeInProgramGuide = true
|
||||||
|
|||||||
@@ -36,22 +36,22 @@ public class AddItemsToPlaylistHandler : IRequestHandler<AddItemsToPlaylist, Eit
|
|||||||
AddItemsToPlaylist request,
|
AddItemsToPlaylist request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var allItems = new Dictionary<ProgramScheduleItemCollectionType, List<int>>
|
var allItems = new Dictionary<CollectionType, List<int>>
|
||||||
{
|
{
|
||||||
{ ProgramScheduleItemCollectionType.Movie, request.MovieIds },
|
{ CollectionType.Movie, request.MovieIds },
|
||||||
{ ProgramScheduleItemCollectionType.TelevisionShow, request.ShowIds },
|
{ CollectionType.TelevisionShow, request.ShowIds },
|
||||||
{ ProgramScheduleItemCollectionType.TelevisionSeason, request.SeasonIds },
|
{ CollectionType.TelevisionSeason, request.SeasonIds },
|
||||||
{ ProgramScheduleItemCollectionType.Episode, request.EpisodeIds },
|
{ CollectionType.Episode, request.EpisodeIds },
|
||||||
{ ProgramScheduleItemCollectionType.Artist, request.ArtistIds },
|
{ CollectionType.Artist, request.ArtistIds },
|
||||||
{ ProgramScheduleItemCollectionType.MusicVideo, request.MusicVideoIds },
|
{ CollectionType.MusicVideo, request.MusicVideoIds },
|
||||||
{ ProgramScheduleItemCollectionType.OtherVideo, request.OtherVideoIds },
|
{ CollectionType.OtherVideo, request.OtherVideoIds },
|
||||||
{ ProgramScheduleItemCollectionType.Song, request.SongIds },
|
{ CollectionType.Song, request.SongIds },
|
||||||
{ ProgramScheduleItemCollectionType.Image, request.ImageIds }
|
{ CollectionType.Image, request.ImageIds }
|
||||||
};
|
};
|
||||||
|
|
||||||
int index = playlist.Items.Count > 0 ? playlist.Items.Max(i => i.Index) + 1 : 0;
|
int index = playlist.Items.Count > 0 ? playlist.Items.Max(i => i.Index) + 1 : 0;
|
||||||
|
|
||||||
foreach ((ProgramScheduleItemCollectionType collectionType, List<int> ids) in allItems)
|
foreach ((CollectionType collectionType, List<int> ids) in allItems)
|
||||||
{
|
{
|
||||||
foreach (int id in ids)
|
foreach (int id in ids)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class AddMovieToPlaylistHandler(IDbContextFactory<TvContext> dbContextFac
|
|||||||
var playlistItem = new PlaylistItem
|
var playlistItem = new PlaylistItem
|
||||||
{
|
{
|
||||||
Index = index,
|
Index = index,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Movie,
|
CollectionType = CollectionType.Movie,
|
||||||
MediaItemId = parameters.Movie.Id,
|
MediaItemId = parameters.Movie.Id,
|
||||||
PlaybackOrder = PlaybackOrder.Shuffle,
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
IncludeInProgramGuide = true
|
IncludeInProgramGuide = true
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class AddSeasonToPlaylistHandler(IDbContextFactory<TvContext> dbContextFa
|
|||||||
var playlistItem = new PlaylistItem
|
var playlistItem = new PlaylistItem
|
||||||
{
|
{
|
||||||
Index = index,
|
Index = index,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionSeason,
|
CollectionType = CollectionType.TelevisionSeason,
|
||||||
MediaItemId = parameters.Season.Id,
|
MediaItemId = parameters.Season.Id,
|
||||||
PlaybackOrder = PlaybackOrder.Shuffle,
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
IncludeInProgramGuide = true
|
IncludeInProgramGuide = true
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class AddShowToPlaylistHandler(IDbContextFactory<TvContext> dbContextFact
|
|||||||
var playlistItem = new PlaylistItem
|
var playlistItem = new PlaylistItem
|
||||||
{
|
{
|
||||||
Index = index,
|
Index = index,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType = CollectionType.TelevisionShow,
|
||||||
MediaItemId = parameters.Show.Id,
|
MediaItemId = parameters.Show.Id,
|
||||||
PlaybackOrder = PlaybackOrder.Shuffle,
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
IncludeInProgramGuide = true
|
IncludeInProgramGuide = true
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using ErsatzTV.Application.MediaItems;
|
||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record CreateRerunCollection(
|
||||||
|
string Name,
|
||||||
|
CollectionType CollectionType,
|
||||||
|
MediaCollectionViewModel Collection,
|
||||||
|
MultiCollectionViewModel MultiCollection,
|
||||||
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
NamedMediaItemViewModel MediaItem,
|
||||||
|
PlaybackOrder FirstRunPlaybackOrder,
|
||||||
|
PlaybackOrder RerunPlaybackOrder)
|
||||||
|
: IRequest<Either<BaseError, RerunCollectionViewModel>>;
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using static ErsatzTV.Application.MediaCollections.Mapper;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class CreateRerunCollectionHandler(IDbContextFactory<TvContext> dbContextFactory) :
|
||||||
|
IRequestHandler<CreateRerunCollection, Either<BaseError, RerunCollectionViewModel>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, RerunCollectionViewModel>> Handle(
|
||||||
|
CreateRerunCollection request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, RerunCollection> validation = await Validate(dbContext, request);
|
||||||
|
return await validation.Apply(c => PersistCollection(dbContext, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<RerunCollectionViewModel> PersistCollection(
|
||||||
|
TvContext dbContext,
|
||||||
|
RerunCollection collection)
|
||||||
|
{
|
||||||
|
await dbContext.RerunCollections.AddAsync(collection);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
return ProjectToViewModel(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, RerunCollection>> Validate(
|
||||||
|
TvContext dbContext,
|
||||||
|
CreateRerunCollection request) =>
|
||||||
|
ValidateName(dbContext, request).MapT(name => new RerunCollection
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
CollectionType = request.CollectionType,
|
||||||
|
CollectionId = request.Collection?.Id,
|
||||||
|
MultiCollectionId = request.MultiCollection?.Id,
|
||||||
|
SmartCollectionId = request.SmartCollection?.Id,
|
||||||
|
MediaItemId = request.MediaItem?.MediaItemId,
|
||||||
|
FirstRunPlaybackOrder = request.FirstRunPlaybackOrder,
|
||||||
|
RerunPlaybackOrder = request.RerunPlaybackOrder
|
||||||
|
});
|
||||||
|
|
||||||
|
private static async Task<Validation<BaseError, string>> ValidateName(
|
||||||
|
TvContext dbContext,
|
||||||
|
CreateRerunCollection createCollection)
|
||||||
|
{
|
||||||
|
List<string> allNames = await dbContext.RerunCollections
|
||||||
|
.Map(c => c.Name)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
Validation<BaseError, string> result1 = createCollection.NotEmpty(c => c.Name)
|
||||||
|
.Bind(_ => createCollection.NotLongerThan(50)(c => c.Name));
|
||||||
|
|
||||||
|
var result2 = Optional(createCollection.Name)
|
||||||
|
.Where(name => !allNames.Contains(name))
|
||||||
|
.ToValidation<BaseError>("Rerun collection name must be unique");
|
||||||
|
|
||||||
|
return (result1, result2).Apply((_, _) => createCollection.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record DeleteRerunCollection(int RerunCollectionId) : IRequest<Either<BaseError, Unit>>;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class DeleteRerunCollectionHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<DeleteRerunCollection, Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, Unit>> Handle(
|
||||||
|
DeleteRerunCollection request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, RerunCollection> validation = await RerunCollectionMustExist(
|
||||||
|
dbContext,
|
||||||
|
request,
|
||||||
|
cancellationToken);
|
||||||
|
return await validation.Apply(c => DoDeletion(dbContext, c, cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Unit> DoDeletion(
|
||||||
|
TvContext dbContext,
|
||||||
|
RerunCollection rerunCollection,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
dbContext.RerunCollections.Remove(rerunCollection);
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, RerunCollection>> RerunCollectionMustExist(
|
||||||
|
TvContext dbContext,
|
||||||
|
DeleteRerunCollection request,
|
||||||
|
CancellationToken cancellationToken) =>
|
||||||
|
dbContext.RerunCollections
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == request.RerunCollectionId, cancellationToken)
|
||||||
|
.Map(o => o.ToValidation<BaseError>($"Rerun collection {request.RerunCollectionId} does not exist."));
|
||||||
|
}
|
||||||
@@ -120,7 +120,7 @@ public class PreviewPlaylistPlayoutHandler(
|
|||||||
private static ProgramScheduleItemFlood MapToScheduleItem(PreviewPlaylistPlayout request) =>
|
private static ProgramScheduleItemFlood MapToScheduleItem(PreviewPlaylistPlayout request) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Playlist,
|
CollectionType = CollectionType.Playlist,
|
||||||
Playlist = new Playlist
|
Playlist = new Playlist
|
||||||
{
|
{
|
||||||
Items = request.Data.Items.OrderBy(i => i.Index).Map(MapToPlaylistItem).ToList()
|
Items = request.Data.Items.OrderBy(i => i.Index).Map(MapToPlaylistItem).ToList()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace ErsatzTV.Application.MediaCollections;
|
|||||||
|
|
||||||
public record ReplacePlaylistItem(
|
public record ReplacePlaylistItem(
|
||||||
int Index,
|
int Index,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
|||||||
@@ -78,61 +78,61 @@ public class ReplacePlaylistItemsHandler(IDbContextFactory<TvContext> dbContextF
|
|||||||
{
|
{
|
||||||
switch (item.CollectionType)
|
switch (item.CollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
if (item.CollectionId is null)
|
if (item.CollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionShow:
|
case CollectionType.TelevisionShow:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionSeason:
|
case CollectionType.TelevisionSeason:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Artist:
|
case CollectionType.Artist:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
if (item.MultiCollectionId is null)
|
if (item.MultiCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
if (item.SmartCollectionId is null)
|
if (item.SmartCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Movie:
|
case CollectionType.Movie:
|
||||||
case ProgramScheduleItemCollectionType.Episode:
|
case CollectionType.Episode:
|
||||||
case ProgramScheduleItemCollectionType.MusicVideo:
|
case CollectionType.MusicVideo:
|
||||||
case ProgramScheduleItemCollectionType.OtherVideo:
|
case CollectionType.OtherVideo:
|
||||||
case ProgramScheduleItemCollectionType.Song:
|
case CollectionType.Song:
|
||||||
case ProgramScheduleItemCollectionType.Image:
|
case CollectionType.Image:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New($"[MediaItem] is required for type '{item.CollectionType}'");
|
return BaseError.New($"[MediaItem] is required for type '{item.CollectionType}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.FakeCollection:
|
case CollectionType.FakeCollection:
|
||||||
default:
|
default:
|
||||||
return BaseError.New("[CollectionType] is invalid");
|
return BaseError.New("[CollectionType] is invalid");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,10 +203,10 @@ public abstract class TraktCommandBase
|
|||||||
|
|
||||||
playlistItem.CollectionType = item.Kind switch
|
playlistItem.CollectionType = item.Kind switch
|
||||||
{
|
{
|
||||||
TraktListItemKind.Movie => ProgramScheduleItemCollectionType.Movie,
|
TraktListItemKind.Movie => CollectionType.Movie,
|
||||||
TraktListItemKind.Show => ProgramScheduleItemCollectionType.TelevisionShow,
|
TraktListItemKind.Show => CollectionType.TelevisionShow,
|
||||||
TraktListItemKind.Season => ProgramScheduleItemCollectionType.TelevisionSeason,
|
TraktListItemKind.Season => CollectionType.TelevisionSeason,
|
||||||
_ => ProgramScheduleItemCollectionType.Episode
|
_ => CollectionType.Episode
|
||||||
};
|
};
|
||||||
|
|
||||||
playlistItem.MediaItemId = item.MediaItemId;
|
playlistItem.MediaItemId = item.MediaItemId;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using ErsatzTV.Application.MediaItems;
|
||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record UpdateRerunCollection(
|
||||||
|
int RerunCollectionId,
|
||||||
|
string Name,
|
||||||
|
CollectionType CollectionType,
|
||||||
|
MediaCollectionViewModel Collection,
|
||||||
|
MultiCollectionViewModel MultiCollection,
|
||||||
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
NamedMediaItemViewModel MediaItem,
|
||||||
|
PlaybackOrder FirstRunPlaybackOrder,
|
||||||
|
PlaybackOrder RerunPlaybackOrder)
|
||||||
|
: IRequest<Either<BaseError, Unit>>;
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using System.Threading.Channels;
|
||||||
|
using ErsatzTV.Application.Playouts;
|
||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
|
using ErsatzTV.Core.Scheduling;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class UpdateRerunCollectionHandler(
|
||||||
|
IDbContextFactory<TvContext> dbContextFactory,
|
||||||
|
IMediaCollectionRepository mediaCollectionRepository,
|
||||||
|
ChannelWriter<IBackgroundServiceRequest> channel)
|
||||||
|
: IRequestHandler<UpdateRerunCollection, Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, Unit>> Handle(
|
||||||
|
UpdateRerunCollection request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, RerunCollection> validation = await Validate(dbContext, request, cancellationToken);
|
||||||
|
return await validation.Apply(c => ApplyUpdateRequest(dbContext, c, request, cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Unit> ApplyUpdateRequest(
|
||||||
|
TvContext dbContext,
|
||||||
|
RerunCollection c,
|
||||||
|
UpdateRerunCollection request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
c.Name = request.Name;
|
||||||
|
c.CollectionType = request.CollectionType;
|
||||||
|
c.CollectionId = request.Collection?.Id;
|
||||||
|
c.MultiCollectionId = request.MultiCollection?.Id;
|
||||||
|
c.SmartCollectionId = request.SmartCollection?.Id;
|
||||||
|
c.MediaItemId = request.MediaItem?.MediaItemId;
|
||||||
|
c.FirstRunPlaybackOrder = request.FirstRunPlaybackOrder;
|
||||||
|
c.RerunPlaybackOrder = request.RerunPlaybackOrder;
|
||||||
|
|
||||||
|
// rebuild playouts
|
||||||
|
if (await dbContext.SaveChangesAsync(cancellationToken) > 0)
|
||||||
|
{
|
||||||
|
// refresh all playouts that use this rerun collection
|
||||||
|
foreach (int playoutId in await mediaCollectionRepository.PlayoutIdsUsingRerunCollection(
|
||||||
|
request.RerunCollectionId))
|
||||||
|
{
|
||||||
|
await channel.WriteAsync(new BuildPlayout(playoutId, PlayoutBuildMode.Refresh), cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, RerunCollection>> Validate(
|
||||||
|
TvContext dbContext,
|
||||||
|
UpdateRerunCollection request,
|
||||||
|
CancellationToken cancellationToken) => RerunCollectionMustExist(dbContext, request, cancellationToken);
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, RerunCollection>> RerunCollectionMustExist(
|
||||||
|
TvContext dbContext,
|
||||||
|
UpdateRerunCollection updateCollection,
|
||||||
|
CancellationToken cancellationToken) =>
|
||||||
|
dbContext.RerunCollections
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == updateCollection.RerunCollectionId, cancellationToken)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Rerun collection does not exist."));
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ internal static class Mapper
|
|||||||
{
|
{
|
||||||
internal static MediaCollectionViewModel ProjectToViewModel(Collection collection) =>
|
internal static MediaCollectionViewModel ProjectToViewModel(Collection collection) =>
|
||||||
new(
|
new(
|
||||||
ProgramScheduleItemCollectionType.Collection,
|
CollectionType.Collection,
|
||||||
collection.Id,
|
collection.Id,
|
||||||
collection.Name,
|
collection.Name,
|
||||||
collection.UseCustomPlaybackOrder,
|
collection.UseCustomPlaybackOrder,
|
||||||
@@ -23,6 +23,30 @@ internal static class Mapper
|
|||||||
internal static SmartCollectionViewModel ProjectToViewModel(SmartCollection collection) =>
|
internal static SmartCollectionViewModel ProjectToViewModel(SmartCollection collection) =>
|
||||||
new(collection.Id, collection.Name, collection.Query);
|
new(collection.Id, collection.Name, collection.Query);
|
||||||
|
|
||||||
|
internal static RerunCollectionViewModel ProjectToViewModel(RerunCollection collection) =>
|
||||||
|
new(
|
||||||
|
collection.Id,
|
||||||
|
collection.Name,
|
||||||
|
collection.CollectionType,
|
||||||
|
collection.Collection is not null ? ProjectToViewModel(collection.Collection) : null,
|
||||||
|
collection.MultiCollection is not null ? ProjectToViewModel(collection.MultiCollection) : null,
|
||||||
|
collection.SmartCollection is not null ? ProjectToViewModel(collection.SmartCollection) : null,
|
||||||
|
collection.MediaItem switch
|
||||||
|
{
|
||||||
|
Show show => MediaItems.Mapper.ProjectToViewModel(show),
|
||||||
|
Season season => MediaItems.Mapper.ProjectToViewModel(season),
|
||||||
|
Artist artist => MediaItems.Mapper.ProjectToViewModel(artist),
|
||||||
|
Movie movie => MediaItems.Mapper.ProjectToViewModel(movie),
|
||||||
|
Episode episode => MediaItems.Mapper.ProjectToViewModel(episode),
|
||||||
|
MusicVideo musicVideo => MediaItems.Mapper.ProjectToViewModel(musicVideo),
|
||||||
|
OtherVideo otherVideo => MediaItems.Mapper.ProjectToViewModel(otherVideo),
|
||||||
|
Song song => MediaItems.Mapper.ProjectToViewModel(song),
|
||||||
|
Image image => MediaItems.Mapper.ProjectToViewModel(image),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
collection.FirstRunPlaybackOrder,
|
||||||
|
collection.RerunPlaybackOrder);
|
||||||
|
|
||||||
internal static TraktListViewModel ProjectToViewModel(TraktList traktList) =>
|
internal static TraktListViewModel ProjectToViewModel(TraktList traktList) =>
|
||||||
new(
|
new(
|
||||||
traktList.Id,
|
traktList.Id,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using ErsatzTV.Core.Domain;
|
|||||||
namespace ErsatzTV.Application.MediaCollections;
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
public record MediaCollectionViewModel(
|
public record MediaCollectionViewModel(
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int Id,
|
int Id,
|
||||||
string Name,
|
string Name,
|
||||||
bool UseCustomPlaybackOrder,
|
bool UseCustomPlaybackOrder,
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record PagedRerunCollectionsViewModel(int TotalCount, List<RerunCollectionViewModel> Page);
|
||||||
@@ -6,7 +6,7 @@ namespace ErsatzTV.Application.MediaCollections;
|
|||||||
public record PlaylistItemViewModel(
|
public record PlaylistItemViewModel(
|
||||||
int Id,
|
int Id,
|
||||||
int Index,
|
int Index,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
MediaCollectionViewModel Collection,
|
MediaCollectionViewModel Collection,
|
||||||
MultiCollectionViewModel MultiCollection,
|
MultiCollectionViewModel MultiCollection,
|
||||||
SmartCollectionViewModel SmartCollection,
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record GetPagedRerunCollections(int PageNum, int PageSize) : IRequest<PagedRerunCollectionsViewModel>;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using static ErsatzTV.Application.MediaCollections.Mapper;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class GetPagedRerunCollectionsHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<GetPagedRerunCollections, PagedRerunCollectionsViewModel>
|
||||||
|
{
|
||||||
|
public async Task<PagedRerunCollectionsViewModel> Handle(
|
||||||
|
GetPagedRerunCollections request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
int count = await dbContext.RerunCollections.CountAsync(cancellationToken);
|
||||||
|
List<RerunCollectionViewModel> page = await dbContext.RerunCollections
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderBy(f => EF.Functions.Collate(f.Name, TvContext.CaseInsensitiveCollation))
|
||||||
|
.Skip(request.PageNum * request.PageSize)
|
||||||
|
.Take(request.PageSize)
|
||||||
|
.ToListAsync(cancellationToken)
|
||||||
|
.Map(list => list.Map(ProjectToViewModel).ToList());
|
||||||
|
|
||||||
|
return new PagedRerunCollectionsViewModel(count, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,18 +4,14 @@ using static ErsatzTV.Application.MediaCollections.Mapper;
|
|||||||
|
|
||||||
namespace ErsatzTV.Application.MediaCollections;
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
public class GetPagedSmartCollectionsHandler : IRequestHandler<GetPagedSmartCollections, PagedSmartCollectionsViewModel>
|
public class GetPagedSmartCollectionsHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<GetPagedSmartCollections, PagedSmartCollectionsViewModel>
|
||||||
{
|
{
|
||||||
private readonly IDbContextFactory<TvContext> _dbContextFactory;
|
|
||||||
|
|
||||||
public GetPagedSmartCollectionsHandler(IDbContextFactory<TvContext> dbContextFactory) =>
|
|
||||||
_dbContextFactory = dbContextFactory;
|
|
||||||
|
|
||||||
public async Task<PagedSmartCollectionsViewModel> Handle(
|
public async Task<PagedSmartCollectionsViewModel> Handle(
|
||||||
GetPagedSmartCollections request,
|
GetPagedSmartCollections request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
int count = await dbContext.SmartCollections.CountAsync(cancellationToken);
|
int count = await dbContext.SmartCollections.CountAsync(cancellationToken);
|
||||||
List<SmartCollectionViewModel> page = await dbContext.SmartCollections
|
List<SmartCollectionViewModel> page = await dbContext.SmartCollections
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record GetRerunCollectionById(int Id) : IRequest<Option<RerunCollectionViewModel>>;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using static ErsatzTV.Application.MediaCollections.Mapper;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class GetRerunCollectionByIdHandler(IDbContextFactory<TvContext> dbContextFactory) :
|
||||||
|
IRequestHandler<GetRerunCollectionById, Option<RerunCollectionViewModel>>
|
||||||
|
{
|
||||||
|
public async Task<Option<RerunCollectionViewModel>> Handle(
|
||||||
|
GetRerunCollectionById request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
return await dbContext.RerunCollections
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(c => c.Collection)
|
||||||
|
.Include(c => c.MultiCollection)
|
||||||
|
.Include(c => c.SmartCollection)
|
||||||
|
.Include(i => i.MediaItem)
|
||||||
|
.ThenInclude(i => (i as Movie).MovieMetadata)
|
||||||
|
.Include(i => i.MediaItem)
|
||||||
|
.ThenInclude(i => (i as Season).SeasonMetadata)
|
||||||
|
.Include(i => i.MediaItem)
|
||||||
|
.ThenInclude(i => (i as Season).Show)
|
||||||
|
.ThenInclude(s => s.ShowMetadata)
|
||||||
|
.Include(i => i.MediaItem)
|
||||||
|
.ThenInclude(i => (i as Show).ShowMetadata)
|
||||||
|
.Include(i => i.MediaItem)
|
||||||
|
.ThenInclude(i => (i as Artist).ArtistMetadata)
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == request.Id, cancellationToken)
|
||||||
|
.MapT(ProjectToViewModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using ErsatzTV.Application.MediaItems;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record RerunCollectionViewModel(
|
||||||
|
int Id,
|
||||||
|
string Name,
|
||||||
|
CollectionType CollectionType,
|
||||||
|
MediaCollectionViewModel Collection,
|
||||||
|
MultiCollectionViewModel MultiCollection,
|
||||||
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
NamedMediaItemViewModel MediaItem,
|
||||||
|
PlaybackOrder FirstRunPlaybackOrder,
|
||||||
|
PlaybackOrder RerunPlaybackOrder);
|
||||||
@@ -28,6 +28,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
|
|||||||
private readonly IFFmpegSegmenterService _ffmpegSegmenterService;
|
private readonly IFFmpegSegmenterService _ffmpegSegmenterService;
|
||||||
private readonly IPlayoutBuilder _playoutBuilder;
|
private readonly IPlayoutBuilder _playoutBuilder;
|
||||||
private readonly IPlayoutTimeShifter _playoutTimeShifter;
|
private readonly IPlayoutTimeShifter _playoutTimeShifter;
|
||||||
|
private readonly IRerunHelper _rerunHelper;
|
||||||
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
|
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
|
||||||
private readonly ISequentialPlayoutBuilder _sequentialPlayoutBuilder;
|
private readonly ISequentialPlayoutBuilder _sequentialPlayoutBuilder;
|
||||||
private readonly IScriptedPlayoutBuilder _scriptedPlayoutBuilder;
|
private readonly IScriptedPlayoutBuilder _scriptedPlayoutBuilder;
|
||||||
@@ -44,6 +45,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
|
|||||||
IFFmpegSegmenterService ffmpegSegmenterService,
|
IFFmpegSegmenterService ffmpegSegmenterService,
|
||||||
IEntityLocker entityLocker,
|
IEntityLocker entityLocker,
|
||||||
IPlayoutTimeShifter playoutTimeShifter,
|
IPlayoutTimeShifter playoutTimeShifter,
|
||||||
|
IRerunHelper rerunHelper,
|
||||||
ChannelWriter<IBackgroundServiceRequest> workerChannel)
|
ChannelWriter<IBackgroundServiceRequest> workerChannel)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
@@ -57,6 +59,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
|
|||||||
_ffmpegSegmenterService = ffmpegSegmenterService;
|
_ffmpegSegmenterService = ffmpegSegmenterService;
|
||||||
_entityLocker = entityLocker;
|
_entityLocker = entityLocker;
|
||||||
_playoutTimeShifter = playoutTimeShifter;
|
_playoutTimeShifter = playoutTimeShifter;
|
||||||
|
_rerunHelper = rerunHelper;
|
||||||
_workerChannel = workerChannel;
|
_workerChannel = workerChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +163,19 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
|
|||||||
|
|
||||||
var changeCount = 0;
|
var changeCount = 0;
|
||||||
|
|
||||||
|
if (result.RerunHistoryToRemove.Count > 0)
|
||||||
|
{
|
||||||
|
changeCount += await dbContext.RerunHistory
|
||||||
|
.Where(rh => result.RerunHistoryToRemove.Contains(rh.Id))
|
||||||
|
.ExecuteDeleteAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.AddedRerunHistory.Count > 0)
|
||||||
|
{
|
||||||
|
changeCount += 1;
|
||||||
|
await dbContext.BulkInsertAsync(result.AddedRerunHistory, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (result.ClearItems)
|
if (result.ClearItems)
|
||||||
{
|
{
|
||||||
changeCount += await dbContext.PlayoutItems
|
changeCount += await dbContext.PlayoutItems
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ public record AddProgramScheduleItem(
|
|||||||
TimeSpan? StartTime,
|
TimeSpan? StartTime,
|
||||||
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
||||||
PlayoutMode PlayoutMode,
|
PlayoutMode PlayoutMode,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
int? RerunCollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? PlaylistId,
|
int? PlaylistId,
|
||||||
PlaybackOrder PlaybackOrder,
|
PlaybackOrder PlaybackOrder,
|
||||||
@@ -42,7 +43,7 @@ public record AddProgramScheduleItem(
|
|||||||
ChannelSubtitleMode? SubtitleMode) : IRequest<Either<BaseError, ProgramScheduleItemViewModel>>,
|
ChannelSubtitleMode? SubtitleMode) : IRequest<Either<BaseError, ProgramScheduleItemViewModel>>,
|
||||||
IProgramScheduleItemRequest
|
IProgramScheduleItemRequest
|
||||||
{
|
{
|
||||||
public static AddProgramScheduleItem ForMediaItem(int scheduleId, ProgramScheduleItemCollectionType collectionType, int mediaItemId)
|
public static AddProgramScheduleItem ForMediaItem(int scheduleId, CollectionType collectionType, int mediaItemId)
|
||||||
=> new(
|
=> new(
|
||||||
scheduleId,
|
scheduleId,
|
||||||
StartType.Dynamic,
|
StartType.Dynamic,
|
||||||
@@ -53,6 +54,7 @@ public record AddProgramScheduleItem(
|
|||||||
CollectionId: null,
|
CollectionId: null,
|
||||||
MultiCollectionId: null,
|
MultiCollectionId: null,
|
||||||
SmartCollectionId: null,
|
SmartCollectionId: null,
|
||||||
|
RerunCollectionId: null,
|
||||||
MediaItemId: mediaItemId,
|
MediaItemId: mediaItemId,
|
||||||
PlaylistId: null,
|
PlaylistId: null,
|
||||||
PlaybackOrder.Shuffle,
|
PlaybackOrder.Shuffle,
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ public interface IProgramScheduleItemRequest
|
|||||||
{
|
{
|
||||||
TimeSpan? StartTime { get; }
|
TimeSpan? StartTime { get; }
|
||||||
FixedStartTimeBehavior? FixedStartTimeBehavior { get; }
|
FixedStartTimeBehavior? FixedStartTimeBehavior { get; }
|
||||||
ProgramScheduleItemCollectionType CollectionType { get; }
|
CollectionType CollectionType { get; }
|
||||||
int? CollectionId { get; }
|
int? CollectionId { get; }
|
||||||
int? MultiCollectionId { get; }
|
int? MultiCollectionId { get; }
|
||||||
int? SmartCollectionId { get; }
|
int? SmartCollectionId { get; }
|
||||||
|
int? RerunCollectionId { get; }
|
||||||
int? MediaItemId { get; }
|
int? MediaItemId { get; }
|
||||||
int? PlaylistId { get; }
|
int? PlaylistId { get; }
|
||||||
PlayoutMode PlayoutMode { get; }
|
PlayoutMode PlayoutMode { get; }
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
break;
|
break;
|
||||||
case PlayoutMode.Multiple:
|
case PlayoutMode.Multiple:
|
||||||
if (item.MultipleMode is MultipleMode.PlaylistItemSize &&
|
if (item.MultipleMode is MultipleMode.PlaylistItemSize &&
|
||||||
item.CollectionType is not ProgramScheduleItemCollectionType.Playlist)
|
item.CollectionType is not CollectionType.Playlist)
|
||||||
{
|
{
|
||||||
return BaseError.New(
|
return BaseError.New(
|
||||||
"[MultipleMode] cannot be [PlaylistItemSize] when collection is not a playlist");
|
"[MultipleMode] cannot be [PlaylistItemSize] when collection is not a playlist");
|
||||||
@@ -126,49 +126,63 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
{
|
{
|
||||||
switch (item.CollectionType)
|
switch (item.CollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
if (item.CollectionId is null)
|
if (item.CollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionShow:
|
case CollectionType.TelevisionShow:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionSeason:
|
case CollectionType.TelevisionSeason:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Artist:
|
case CollectionType.Artist:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
if (item.MultiCollectionId is null)
|
if (item.MultiCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
if (item.SmartCollectionId is null)
|
if (item.SmartCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Playlist:
|
case CollectionType.RerunFirstRun:
|
||||||
|
if (item.RerunCollectionId is null)
|
||||||
|
{
|
||||||
|
return BaseError.New("[RerunCollection] is required for collection type 'RerunFirstRun'");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CollectionType.RerunRerun:
|
||||||
|
if (item.RerunCollectionId is null)
|
||||||
|
{
|
||||||
|
return BaseError.New("[RerunCollection] is required for collection type 'RerunRerun'");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CollectionType.Playlist:
|
||||||
if (item.PlaylistId is null)
|
if (item.PlaylistId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[Playlist] is required for collection type 'Playlist'");
|
return BaseError.New("[Playlist] is required for collection type 'Playlist'");
|
||||||
@@ -199,6 +213,7 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
CollectionId = item.CollectionId,
|
CollectionId = item.CollectionId,
|
||||||
MultiCollectionId = item.MultiCollectionId,
|
MultiCollectionId = item.MultiCollectionId,
|
||||||
SmartCollectionId = item.SmartCollectionId,
|
SmartCollectionId = item.SmartCollectionId,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
PlaylistId = item.PlaylistId,
|
PlaylistId = item.PlaylistId,
|
||||||
PlaybackOrder = item.PlaybackOrder,
|
PlaybackOrder = item.PlaybackOrder,
|
||||||
@@ -229,6 +244,7 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
CollectionId = item.CollectionId,
|
CollectionId = item.CollectionId,
|
||||||
MultiCollectionId = item.MultiCollectionId,
|
MultiCollectionId = item.MultiCollectionId,
|
||||||
SmartCollectionId = item.SmartCollectionId,
|
SmartCollectionId = item.SmartCollectionId,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
PlaylistId = item.PlaylistId,
|
PlaylistId = item.PlaylistId,
|
||||||
PlaybackOrder = item.PlaybackOrder,
|
PlaybackOrder = item.PlaybackOrder,
|
||||||
@@ -259,6 +275,7 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
CollectionId = item.CollectionId,
|
CollectionId = item.CollectionId,
|
||||||
MultiCollectionId = item.MultiCollectionId,
|
MultiCollectionId = item.MultiCollectionId,
|
||||||
SmartCollectionId = item.SmartCollectionId,
|
SmartCollectionId = item.SmartCollectionId,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
PlaylistId = item.PlaylistId,
|
PlaylistId = item.PlaylistId,
|
||||||
PlaybackOrder = item.PlaybackOrder,
|
PlaybackOrder = item.PlaybackOrder,
|
||||||
@@ -291,6 +308,7 @@ public abstract class ProgramScheduleItemCommandBase
|
|||||||
CollectionId = item.CollectionId,
|
CollectionId = item.CollectionId,
|
||||||
MultiCollectionId = item.MultiCollectionId,
|
MultiCollectionId = item.MultiCollectionId,
|
||||||
SmartCollectionId = item.SmartCollectionId,
|
SmartCollectionId = item.SmartCollectionId,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
PlaylistId = item.PlaylistId,
|
PlaylistId = item.PlaylistId,
|
||||||
PlaybackOrder = item.PlaybackOrder,
|
PlaybackOrder = item.PlaybackOrder,
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ public record ReplaceProgramScheduleItem(
|
|||||||
TimeSpan? StartTime,
|
TimeSpan? StartTime,
|
||||||
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
||||||
PlayoutMode PlayoutMode,
|
PlayoutMode PlayoutMode,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
int? RerunCollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? PlaylistId,
|
int? PlaylistId,
|
||||||
PlaybackOrder PlaybackOrder,
|
PlaybackOrder PlaybackOrder,
|
||||||
|
|||||||
+3
-1
@@ -120,6 +120,7 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase
|
|||||||
item.MediaItemId,
|
item.MediaItemId,
|
||||||
item.MultiCollectionId,
|
item.MultiCollectionId,
|
||||||
item.SmartCollectionId,
|
item.SmartCollectionId,
|
||||||
|
item.RerunCollectionId,
|
||||||
item.PlaylistId);
|
item.PlaylistId);
|
||||||
|
|
||||||
if (keyOrders.TryGetValue(key, out System.Collections.Generic.HashSet<PlaybackOrder> playbackOrders))
|
if (keyOrders.TryGetValue(key, out System.Collections.Generic.HashSet<PlaybackOrder> playbackOrders))
|
||||||
@@ -140,10 +141,11 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
private sealed record CollectionKey(
|
private sealed record CollectionKey(
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
int? RerunCollectionId,
|
||||||
int? PlaylistId);
|
int? PlaylistId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ internal static class Mapper
|
|||||||
duration.SmartCollection != null
|
duration.SmartCollection != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(duration.SmartCollection)
|
? MediaCollections.Mapper.ProjectToViewModel(duration.SmartCollection)
|
||||||
: null,
|
: null,
|
||||||
|
duration.RerunCollection != null
|
||||||
|
? MediaCollections.Mapper.ProjectToViewModel(duration.RerunCollection)
|
||||||
|
: null,
|
||||||
duration.Playlist != null
|
duration.Playlist != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(duration.Playlist)
|
? MediaCollections.Mapper.ProjectToViewModel(duration.Playlist)
|
||||||
: null,
|
: null,
|
||||||
@@ -95,6 +98,9 @@ internal static class Mapper
|
|||||||
flood.SmartCollection != null
|
flood.SmartCollection != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(flood.SmartCollection)
|
? MediaCollections.Mapper.ProjectToViewModel(flood.SmartCollection)
|
||||||
: null,
|
: null,
|
||||||
|
flood.RerunCollection != null
|
||||||
|
? MediaCollections.Mapper.ProjectToViewModel(flood.RerunCollection)
|
||||||
|
: null,
|
||||||
flood.Playlist != null
|
flood.Playlist != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(flood.Playlist)
|
? MediaCollections.Mapper.ProjectToViewModel(flood.Playlist)
|
||||||
: null,
|
: null,
|
||||||
@@ -153,6 +159,9 @@ internal static class Mapper
|
|||||||
multiple.SmartCollection != null
|
multiple.SmartCollection != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(multiple.SmartCollection)
|
? MediaCollections.Mapper.ProjectToViewModel(multiple.SmartCollection)
|
||||||
: null,
|
: null,
|
||||||
|
multiple.RerunCollection != null
|
||||||
|
? MediaCollections.Mapper.ProjectToViewModel(multiple.RerunCollection)
|
||||||
|
: null,
|
||||||
multiple.Playlist != null
|
multiple.Playlist != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(multiple.Playlist)
|
? MediaCollections.Mapper.ProjectToViewModel(multiple.Playlist)
|
||||||
: null,
|
: null,
|
||||||
@@ -213,6 +222,9 @@ internal static class Mapper
|
|||||||
one.SmartCollection != null
|
one.SmartCollection != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(one.SmartCollection)
|
? MediaCollections.Mapper.ProjectToViewModel(one.SmartCollection)
|
||||||
: null,
|
: null,
|
||||||
|
one.RerunCollection != null
|
||||||
|
? MediaCollections.Mapper.ProjectToViewModel(one.RerunCollection)
|
||||||
|
: null,
|
||||||
one.Playlist != null
|
one.Playlist != null
|
||||||
? MediaCollections.Mapper.ProjectToViewModel(one.Playlist)
|
? MediaCollections.Mapper.ProjectToViewModel(one.Playlist)
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ public record ProgramScheduleItemDurationViewModel : ProgramScheduleItemViewMode
|
|||||||
StartType startType,
|
StartType startType,
|
||||||
TimeSpan? startTime,
|
TimeSpan? startTime,
|
||||||
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
||||||
ProgramScheduleItemCollectionType collectionType,
|
CollectionType collectionType,
|
||||||
MediaCollectionViewModel collection,
|
MediaCollectionViewModel collection,
|
||||||
MultiCollectionViewModel multiCollection,
|
MultiCollectionViewModel multiCollection,
|
||||||
SmartCollectionViewModel smartCollection,
|
SmartCollectionViewModel smartCollection,
|
||||||
|
RerunCollectionViewModel rerunCollection,
|
||||||
PlaylistViewModel playlist,
|
PlaylistViewModel playlist,
|
||||||
NamedMediaItemViewModel mediaItem,
|
NamedMediaItemViewModel mediaItem,
|
||||||
PlaybackOrder playbackOrder,
|
PlaybackOrder playbackOrder,
|
||||||
@@ -54,6 +55,7 @@ public record ProgramScheduleItemDurationViewModel : ProgramScheduleItemViewMode
|
|||||||
collection,
|
collection,
|
||||||
multiCollection,
|
multiCollection,
|
||||||
smartCollection,
|
smartCollection,
|
||||||
|
rerunCollection,
|
||||||
playlist,
|
playlist,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
playbackOrder,
|
playbackOrder,
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ public record ProgramScheduleItemFloodViewModel : ProgramScheduleItemViewModel
|
|||||||
StartType startType,
|
StartType startType,
|
||||||
TimeSpan? startTime,
|
TimeSpan? startTime,
|
||||||
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
||||||
ProgramScheduleItemCollectionType collectionType,
|
CollectionType collectionType,
|
||||||
MediaCollectionViewModel collection,
|
MediaCollectionViewModel collection,
|
||||||
MultiCollectionViewModel multiCollection,
|
MultiCollectionViewModel multiCollection,
|
||||||
SmartCollectionViewModel smartCollection,
|
SmartCollectionViewModel smartCollection,
|
||||||
|
RerunCollectionViewModel rerunCollection,
|
||||||
PlaylistViewModel playlist,
|
PlaylistViewModel playlist,
|
||||||
NamedMediaItemViewModel mediaItem,
|
NamedMediaItemViewModel mediaItem,
|
||||||
PlaybackOrder playbackOrder,
|
PlaybackOrder playbackOrder,
|
||||||
@@ -51,6 +52,7 @@ public record ProgramScheduleItemFloodViewModel : ProgramScheduleItemViewModel
|
|||||||
collection,
|
collection,
|
||||||
multiCollection,
|
multiCollection,
|
||||||
smartCollection,
|
smartCollection,
|
||||||
|
rerunCollection,
|
||||||
playlist,
|
playlist,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
playbackOrder,
|
playbackOrder,
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ public record ProgramScheduleItemMultipleViewModel : ProgramScheduleItemViewMode
|
|||||||
StartType startType,
|
StartType startType,
|
||||||
TimeSpan? startTime,
|
TimeSpan? startTime,
|
||||||
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
||||||
ProgramScheduleItemCollectionType collectionType,
|
CollectionType collectionType,
|
||||||
MediaCollectionViewModel collection,
|
MediaCollectionViewModel collection,
|
||||||
MultiCollectionViewModel multiCollection,
|
MultiCollectionViewModel multiCollection,
|
||||||
SmartCollectionViewModel smartCollection,
|
SmartCollectionViewModel smartCollection,
|
||||||
|
RerunCollectionViewModel rerunCollection,
|
||||||
PlaylistViewModel playlist,
|
PlaylistViewModel playlist,
|
||||||
NamedMediaItemViewModel mediaItem,
|
NamedMediaItemViewModel mediaItem,
|
||||||
PlaybackOrder playbackOrder,
|
PlaybackOrder playbackOrder,
|
||||||
@@ -53,6 +54,7 @@ public record ProgramScheduleItemMultipleViewModel : ProgramScheduleItemViewMode
|
|||||||
collection,
|
collection,
|
||||||
multiCollection,
|
multiCollection,
|
||||||
smartCollection,
|
smartCollection,
|
||||||
|
rerunCollection,
|
||||||
playlist,
|
playlist,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
playbackOrder,
|
playbackOrder,
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ public record ProgramScheduleItemOneViewModel : ProgramScheduleItemViewModel
|
|||||||
StartType startType,
|
StartType startType,
|
||||||
TimeSpan? startTime,
|
TimeSpan? startTime,
|
||||||
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
FixedStartTimeBehavior? fixedStartTimeBehavior,
|
||||||
ProgramScheduleItemCollectionType collectionType,
|
CollectionType collectionType,
|
||||||
MediaCollectionViewModel collection,
|
MediaCollectionViewModel collection,
|
||||||
MultiCollectionViewModel multiCollection,
|
MultiCollectionViewModel multiCollection,
|
||||||
SmartCollectionViewModel smartCollection,
|
SmartCollectionViewModel smartCollection,
|
||||||
|
RerunCollectionViewModel rerunCollection,
|
||||||
PlaylistViewModel playlist,
|
PlaylistViewModel playlist,
|
||||||
NamedMediaItemViewModel mediaItem,
|
NamedMediaItemViewModel mediaItem,
|
||||||
PlaybackOrder playbackOrder,
|
PlaybackOrder playbackOrder,
|
||||||
@@ -51,6 +52,7 @@ public record ProgramScheduleItemOneViewModel : ProgramScheduleItemViewModel
|
|||||||
collection,
|
collection,
|
||||||
multiCollection,
|
multiCollection,
|
||||||
smartCollection,
|
smartCollection,
|
||||||
|
rerunCollection,
|
||||||
playlist,
|
playlist,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
playbackOrder,
|
playbackOrder,
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ public abstract record ProgramScheduleItemViewModel(
|
|||||||
TimeSpan? StartTime,
|
TimeSpan? StartTime,
|
||||||
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
FixedStartTimeBehavior? FixedStartTimeBehavior,
|
||||||
PlayoutMode PlayoutMode,
|
PlayoutMode PlayoutMode,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
MediaCollectionViewModel Collection,
|
MediaCollectionViewModel Collection,
|
||||||
MultiCollectionViewModel MultiCollection,
|
MultiCollectionViewModel MultiCollection,
|
||||||
SmartCollectionViewModel SmartCollection,
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
RerunCollectionViewModel RerunCollection,
|
||||||
PlaylistViewModel Playlist,
|
PlaylistViewModel Playlist,
|
||||||
NamedMediaItemViewModel MediaItem,
|
NamedMediaItemViewModel MediaItem,
|
||||||
PlaybackOrder PlaybackOrder,
|
PlaybackOrder PlaybackOrder,
|
||||||
@@ -43,19 +44,21 @@ public abstract record ProgramScheduleItemViewModel(
|
|||||||
{
|
{
|
||||||
public string Name => CollectionType switch
|
public string Name => CollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => Collection?.Name,
|
CollectionType.Collection => Collection?.Name,
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow =>
|
CollectionType.TelevisionShow =>
|
||||||
MediaItem?.Name, // $"{TelevisionShow?.Title} ({TelevisionShow?.Year})",
|
MediaItem?.Name, // $"{TelevisionShow?.Title} ({TelevisionShow?.Year})",
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason =>
|
CollectionType.TelevisionSeason =>
|
||||||
MediaItem?.Name, // $"{TelevisionSeason?.Title} ({TelevisionSeason?.Plot})",
|
MediaItem?.Name, // $"{TelevisionSeason?.Title} ({TelevisionSeason?.Plot})",
|
||||||
ProgramScheduleItemCollectionType.Artist =>
|
CollectionType.Artist =>
|
||||||
MediaItem?.Name,
|
MediaItem?.Name,
|
||||||
ProgramScheduleItemCollectionType.MultiCollection =>
|
CollectionType.MultiCollection =>
|
||||||
MultiCollection?.Name,
|
MultiCollection?.Name,
|
||||||
ProgramScheduleItemCollectionType.SmartCollection =>
|
CollectionType.SmartCollection =>
|
||||||
SmartCollection?.Name,
|
SmartCollection?.Name,
|
||||||
ProgramScheduleItemCollectionType.Playlist =>
|
CollectionType.Playlist =>
|
||||||
Playlist?.Name,
|
Playlist?.Name,
|
||||||
|
CollectionType.RerunFirstRun or CollectionType.RerunRerun =>
|
||||||
|
RerunCollection?.Name,
|
||||||
_ => string.Empty
|
_ => string.Empty
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class GetProgramScheduleItemsHandler(IDbContextFactory<TvContext> dbConte
|
|||||||
.Include(i => i.Collection)
|
.Include(i => i.Collection)
|
||||||
.Include(i => i.MultiCollection)
|
.Include(i => i.MultiCollection)
|
||||||
.Include(i => i.SmartCollection)
|
.Include(i => i.SmartCollection)
|
||||||
|
.Include(i => i.RerunCollection)
|
||||||
.Include(i => i.Playlist)
|
.Include(i => i.Playlist)
|
||||||
.Include(i => i.MediaItem)
|
.Include(i => i.MediaItem)
|
||||||
.ThenInclude(i => (i as Movie).MovieMetadata)
|
.ThenInclude(i => (i as Movie).MovieMetadata)
|
||||||
@@ -74,6 +75,12 @@ public class GetProgramScheduleItemsHandler(IDbContextFactory<TvContext> dbConte
|
|||||||
{
|
{
|
||||||
item = item with { FillWithGroupMode = FillWithGroupMode.None };
|
item = item with { FillWithGroupMode = FillWithGroupMode.None };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.CollectionType is CollectionType.Playlist or CollectionType.RerunFirstRun
|
||||||
|
or CollectionType.RerunRerun)
|
||||||
|
{
|
||||||
|
item = item with { PlaybackOrder = PlaybackOrder.None };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace ErsatzTV.Application.Scheduling;
|
|||||||
public record BlockItemViewModel(
|
public record BlockItemViewModel(
|
||||||
int Id,
|
int Id,
|
||||||
int Index,
|
int Index,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
MediaCollectionViewModel Collection,
|
MediaCollectionViewModel Collection,
|
||||||
MultiCollectionViewModel MultiCollection,
|
MultiCollectionViewModel MultiCollection,
|
||||||
SmartCollectionViewModel SmartCollection,
|
SmartCollectionViewModel SmartCollection,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace ErsatzTV.Application.Scheduling;
|
|||||||
|
|
||||||
public record ReplaceBlockItem(
|
public record ReplaceBlockItem(
|
||||||
int Index,
|
int Index,
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
|||||||
@@ -89,49 +89,49 @@ public class ReplaceBlockItemsHandler(IDbContextFactory<TvContext> dbContextFact
|
|||||||
{
|
{
|
||||||
switch (item.CollectionType)
|
switch (item.CollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
if (item.CollectionId is null)
|
if (item.CollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
return BaseError.New("[Collection] is required for collection type 'Collection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionShow:
|
case CollectionType.TelevisionShow:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionSeason:
|
case CollectionType.TelevisionSeason:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
return BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Artist:
|
case CollectionType.Artist:
|
||||||
if (item.MediaItemId is null)
|
if (item.MediaItemId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
return BaseError.New("[MediaItem] is required for collection type 'Artist'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
if (item.MultiCollectionId is null)
|
if (item.MultiCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
return BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
if (item.SmartCollectionId is null)
|
if (item.SmartCollectionId is null)
|
||||||
{
|
{
|
||||||
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
return BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.FakeCollection:
|
case CollectionType.FakeCollection:
|
||||||
default:
|
default:
|
||||||
return BaseError.New("[CollectionType] is invalid");
|
return BaseError.New("[CollectionType] is invalid");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ public record UpdateDeco(
|
|||||||
List<int> GraphicsElementIds,
|
List<int> GraphicsElementIds,
|
||||||
bool UseGraphicsElementsDuringFiller,
|
bool UseGraphicsElementsDuringFiller,
|
||||||
DecoMode DefaultFillerMode,
|
DecoMode DefaultFillerMode,
|
||||||
ProgramScheduleItemCollectionType DefaultFillerCollectionType,
|
CollectionType DefaultFillerCollectionType,
|
||||||
int? DefaultFillerCollectionId,
|
int? DefaultFillerCollectionId,
|
||||||
int? DefaultFillerMediaItemId,
|
int? DefaultFillerMediaItemId,
|
||||||
int? DefaultFillerMultiCollectionId,
|
int? DefaultFillerMultiCollectionId,
|
||||||
int? DefaultFillerSmartCollectionId,
|
int? DefaultFillerSmartCollectionId,
|
||||||
bool DefaultFillerTrimToFit,
|
bool DefaultFillerTrimToFit,
|
||||||
DecoMode DeadAirFallbackMode,
|
DecoMode DeadAirFallbackMode,
|
||||||
ProgramScheduleItemCollectionType DeadAirFallbackCollectionType,
|
CollectionType DeadAirFallbackCollectionType,
|
||||||
int? DeadAirFallbackCollectionId,
|
int? DeadAirFallbackCollectionId,
|
||||||
int? DeadAirFallbackMediaItemId,
|
int? DeadAirFallbackMediaItemId,
|
||||||
int? DeadAirFallbackMultiCollectionId,
|
int? DeadAirFallbackMultiCollectionId,
|
||||||
|
|||||||
@@ -92,13 +92,13 @@ public class UpdateDecoHandler(IDbContextFactory<TvContext> dbContextFactory)
|
|||||||
{
|
{
|
||||||
switch (request.DefaultFillerCollectionType)
|
switch (request.DefaultFillerCollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
existing.DefaultFillerCollectionId = request.DefaultFillerCollectionId;
|
existing.DefaultFillerCollectionId = request.DefaultFillerCollectionId;
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
existing.DefaultFillerMultiCollectionId = request.DefaultFillerMultiCollectionId;
|
existing.DefaultFillerMultiCollectionId = request.DefaultFillerMultiCollectionId;
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
existing.DefaultFillerSmartCollectionId = request.DefaultFillerSmartCollectionId;
|
existing.DefaultFillerSmartCollectionId = request.DefaultFillerSmartCollectionId;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -120,13 +120,13 @@ public class UpdateDecoHandler(IDbContextFactory<TvContext> dbContextFactory)
|
|||||||
{
|
{
|
||||||
switch (request.DeadAirFallbackCollectionType)
|
switch (request.DeadAirFallbackCollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
existing.DeadAirFallbackCollectionId = request.DeadAirFallbackCollectionId;
|
existing.DeadAirFallbackCollectionId = request.DeadAirFallbackCollectionId;
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
existing.DeadAirFallbackMultiCollectionId = request.DeadAirFallbackMultiCollectionId;
|
existing.DeadAirFallbackMultiCollectionId = request.DeadAirFallbackMultiCollectionId;
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
existing.DeadAirFallbackSmartCollectionId = request.DeadAirFallbackSmartCollectionId;
|
existing.DeadAirFallbackSmartCollectionId = request.DeadAirFallbackSmartCollectionId;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ public record DecoViewModel(
|
|||||||
List<GraphicsElementViewModel> GraphicsElements,
|
List<GraphicsElementViewModel> GraphicsElements,
|
||||||
bool UseGraphicsElementsDuringFiller,
|
bool UseGraphicsElementsDuringFiller,
|
||||||
DecoMode DefaultFillerMode,
|
DecoMode DefaultFillerMode,
|
||||||
ProgramScheduleItemCollectionType DefaultFillerCollectionType,
|
CollectionType DefaultFillerCollectionType,
|
||||||
int? DefaultFillerCollectionId,
|
int? DefaultFillerCollectionId,
|
||||||
int? DefaultFillerMediaItemId,
|
int? DefaultFillerMediaItemId,
|
||||||
int? DefaultFillerMultiCollectionId,
|
int? DefaultFillerMultiCollectionId,
|
||||||
int? DefaultFillerSmartCollectionId,
|
int? DefaultFillerSmartCollectionId,
|
||||||
bool DefaultFillerTrimToFit,
|
bool DefaultFillerTrimToFit,
|
||||||
DecoMode DeadAirFallbackMode,
|
DecoMode DeadAirFallbackMode,
|
||||||
ProgramScheduleItemCollectionType DeadAirFallbackCollectionType,
|
CollectionType DeadAirFallbackCollectionType,
|
||||||
int? DeadAirFallbackCollectionId,
|
int? DeadAirFallbackCollectionId,
|
||||||
int? DeadAirFallbackMediaItemId,
|
int? DeadAirFallbackMediaItemId,
|
||||||
int? DeadAirFallbackMultiCollectionId,
|
int? DeadAirFallbackMultiCollectionId,
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Search;
|
||||||
|
|
||||||
|
public record SearchRerunCollections(string Query) : IRequest<List<RerunCollectionViewModel>>;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using ErsatzTV.Application.MediaCollections;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using static ErsatzTV.Application.MediaCollections.Mapper;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Search;
|
||||||
|
|
||||||
|
public class SearchRerunCollectionsHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<SearchRerunCollections, List<RerunCollectionViewModel>>
|
||||||
|
{
|
||||||
|
public async Task<List<RerunCollectionViewModel>> Handle(
|
||||||
|
SearchRerunCollections request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
return await dbContext.RerunCollections
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(c => EF.Functions.Like(
|
||||||
|
EF.Functions.Collate(c.Name, TvContext.CaseInsensitiveCollation),
|
||||||
|
$"%{request.Query}%"))
|
||||||
|
.OrderBy(c => EF.Functions.Collate(c.Name, TvContext.CaseInsensitiveCollation))
|
||||||
|
.Take(10)
|
||||||
|
.ToListAsync(cancellationToken)
|
||||||
|
.Map(list => list.Map(ProjectToViewModel).ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -849,7 +849,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
|||||||
private sealed record DisableDeadAirFallback : DeadAirFallbackResult;
|
private sealed record DisableDeadAirFallback : DeadAirFallbackResult;
|
||||||
|
|
||||||
private sealed record CustomDeadAirFallback(
|
private sealed record CustomDeadAirFallback(
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MediaItemId,
|
int? MediaItemId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public class FakeMediaCollectionRepository : IMediaCollectionRepository
|
|||||||
CancellationToken cancellationToken) =>
|
CancellationToken cancellationToken) =>
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
public Task<List<MediaItem>> GetRerunCollectionItems(int id, CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||||
public Task<List<MediaItem>> GetShowItemsByShowGuids(List<string> guids) => throw new NotSupportedException();
|
public Task<List<MediaItem>> GetShowItemsByShowGuids(List<string> guids) => throw new NotSupportedException();
|
||||||
public Task<List<MediaItem>> GetPlaylistItems(int id, CancellationToken cancellationToken) => throw new NotSupportedException();
|
public Task<List<MediaItem>> GetPlaylistItems(int id, CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||||
public Task<List<Movie>> GetMovie(int id) => throw new NotSupportedException();
|
public Task<List<Movie>> GetMovie(int id) => throw new NotSupportedException();
|
||||||
@@ -69,6 +70,9 @@ public class FakeMediaCollectionRepository : IMediaCollectionRepository
|
|||||||
public Task<List<int>> PlayoutIdsUsingSmartCollection(int smartCollectionId) =>
|
public Task<List<int>> PlayoutIdsUsingSmartCollection(int smartCollectionId) =>
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
public Task<List<int>> PlayoutIdsUsingRerunCollection(int rerunCollectionId) =>
|
||||||
|
throw new NotSupportedException();
|
||||||
|
|
||||||
public Task<bool> IsCustomPlaybackOrder(int collectionId) => false.AsTask();
|
public Task<bool> IsCustomPlaybackOrder(int collectionId) => false.AsTask();
|
||||||
public Task<Option<string>> GetNameFromKey(CollectionKey emptyCollection, CancellationToken cancellationToken) => Option<string>.None.AsTask();
|
public Task<Option<string>> GetNameFromKey(CollectionKey emptyCollection, CancellationToken cancellationToken) => Option<string>.None.AsTask();
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ public static class BlockPlayoutChangeDetectionTests
|
|||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
BlockId = 1,
|
BlockId = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType = CollectionType.TelevisionShow,
|
||||||
MediaItemId = 1,
|
MediaItemId = 1,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological
|
PlaybackOrder = PlaybackOrder.Chronological
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ public static class BlockPlayoutChangeDetectionTests
|
|||||||
Id = 2,
|
Id = 2,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
BlockId = 2,
|
BlockId = 2,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType = CollectionType.TelevisionShow,
|
||||||
MediaItemId = 2,
|
MediaItemId = 2,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological
|
PlaybackOrder = PlaybackOrder.Chronological
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ public static class BlockPlayoutChangeDetectionTests
|
|||||||
Id = 3,
|
Id = 3,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
BlockId = 3,
|
BlockId = 3,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType = CollectionType.TelevisionShow,
|
||||||
MediaItemId = 3,
|
MediaItemId = 3,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological
|
PlaybackOrder = PlaybackOrder.Chronological
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class ChronologicalContentTests
|
|||||||
{
|
{
|
||||||
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
||||||
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public class ChronologicalContentTests
|
|||||||
for (var i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
chronologicalContent.State.Index.ShouldBe(i % 10);
|
chronologicalContent.State.Index.ShouldBe(i % 10);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ public class ChronologicalContentTests
|
|||||||
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
||||||
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
chronologicalContent.State.Index.ShouldBe(i - 1);
|
chronologicalContent.State.Index.ShouldBe(i - 1);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -541,6 +541,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -548,6 +549,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -661,6 +663,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -668,6 +671,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -783,6 +787,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -790,6 +795,7 @@ public class ContinuePlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
PlayoutBuildResult result = await builder.Build(
|
PlayoutBuildResult result = await builder.Build(
|
||||||
|
|||||||
@@ -550,6 +550,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -557,6 +558,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -664,6 +666,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -671,6 +674,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -829,6 +833,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -836,6 +841,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -953,6 +959,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -960,6 +967,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1076,6 +1084,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1083,6 +1092,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1200,6 +1210,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1207,6 +1218,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1329,6 +1341,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1336,6 +1349,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1458,6 +1472,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1465,6 +1480,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1596,6 +1612,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1603,6 +1620,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1727,6 +1745,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1734,6 +1753,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
@@ -1824,6 +1844,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -1831,6 +1852,7 @@ public class NewPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(0);
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
collectionRepo,
|
collectionRepo,
|
||||||
@@ -73,6 +74,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, playbackOrder) };
|
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, playbackOrder) };
|
||||||
@@ -120,7 +122,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
Collection = mediaCollection,
|
Collection = mediaCollection,
|
||||||
CollectionId = mediaCollection.Id,
|
CollectionId = mediaCollection.Id,
|
||||||
StartTime = null,
|
StartTime = null,
|
||||||
@@ -135,7 +137,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.SmartCollection,
|
CollectionType = CollectionType.SmartCollection,
|
||||||
SmartCollection = smartCollection,
|
SmartCollection = smartCollection,
|
||||||
SmartCollectionId = smartCollection.Id,
|
SmartCollectionId = smartCollection.Id,
|
||||||
StartTime = null,
|
StartTime = null,
|
||||||
@@ -143,7 +145,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
FallbackFiller = new FillerPreset
|
FallbackFiller = new FillerPreset
|
||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.SmartCollection,
|
CollectionType = CollectionType.SmartCollection,
|
||||||
SmartCollection = fillerCollection,
|
SmartCollection = fillerCollection,
|
||||||
SmartCollectionId = fillerCollection.Id,
|
SmartCollectionId = fillerCollection.Id,
|
||||||
FillerKind = FillerKind.Fallback
|
FillerKind = FillerKind.Fallback
|
||||||
@@ -180,6 +182,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
collectionRepo,
|
collectionRepo,
|
||||||
@@ -187,6 +190,7 @@ public abstract class PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, fillerCollection, playbackOrder) };
|
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, fillerCollection, playbackOrder) };
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class RefreshPlayoutTests : PlayoutBuilderTestBase
|
|||||||
AnchorDate = HoursAfterMidnight(24).UtcDateTime,
|
AnchorDate = HoursAfterMidnight(24).UtcDateTime,
|
||||||
Collection = collectionOne,
|
Collection = collectionOne,
|
||||||
CollectionId = collectionOne.Id,
|
CollectionId = collectionOne.Id,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
EnumeratorState = new CollectionEnumeratorState
|
EnumeratorState = new CollectionEnumeratorState
|
||||||
{
|
{
|
||||||
Index = 1,
|
Index = 1,
|
||||||
@@ -102,6 +102,7 @@ public class RefreshPlayoutTests : PlayoutBuilderTestBase
|
|||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||||
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>();
|
||||||
|
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||||
var builder = new PlayoutBuilder(
|
var builder = new PlayoutBuilder(
|
||||||
configRepo,
|
configRepo,
|
||||||
fakeRepository,
|
fakeRepository,
|
||||||
@@ -109,6 +110,7 @@ public class RefreshPlayoutTests : PlayoutBuilderTestBase
|
|||||||
artistRepo,
|
artistRepo,
|
||||||
factory,
|
factory,
|
||||||
localFileSystem,
|
localFileSystem,
|
||||||
|
rerunHelper,
|
||||||
Logger);
|
Logger);
|
||||||
|
|
||||||
DateTimeOffset start = HoursAfterMidnight(24);
|
DateTimeOffset start = HoursAfterMidnight(24);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class CustomOrderContentTests
|
|||||||
{
|
{
|
||||||
customOrderContent.Current.IsSome.ShouldBeTrue();
|
customOrderContent.Current.IsSome.ShouldBeTrue();
|
||||||
customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
customOrderContent.MoveNext();
|
customOrderContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ public class CustomOrderContentTests
|
|||||||
for (var i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
customOrderContent.State.Index.ShouldBe(i % 10);
|
customOrderContent.State.Index.ShouldBe(i % 10);
|
||||||
customOrderContent.MoveNext();
|
customOrderContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ public class CustomOrderContentTests
|
|||||||
customOrderContent.Current.IsSome.ShouldBeTrue();
|
customOrderContent.Current.IsSome.ShouldBeTrue();
|
||||||
customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
customOrderContent.State.Index.ShouldBe(5 - i + 5); // 5 through 10
|
customOrderContent.State.Index.ShouldBe(5 - i + 5); // 5 through 10
|
||||||
customOrderContent.MoveNext();
|
customOrderContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 1,
|
Id = 1,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 1
|
CollectionId = 1
|
||||||
},
|
},
|
||||||
[FakeMovie(10)]
|
[FakeMovie(10)]
|
||||||
@@ -38,7 +38,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 2,
|
Id = 2,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = true,
|
PlayAll = true,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 2
|
CollectionId = 2
|
||||||
},
|
},
|
||||||
[FakeMovie(20), FakeMovie(21)]
|
[FakeMovie(20), FakeMovie(21)]
|
||||||
@@ -49,7 +49,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 3,
|
Id = 3,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 3
|
CollectionId = 3
|
||||||
},
|
},
|
||||||
[FakeMovie(30), FakeMovie(31)]
|
[FakeMovie(30), FakeMovie(31)]
|
||||||
@@ -67,11 +67,11 @@ public class PlaylistEnumeratorTests
|
|||||||
var items = new List<int>();
|
var items = new List<int>();
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
|
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
while (enumerator.State.Index > 0)
|
while (enumerator.State.Index > 0)
|
||||||
{
|
{
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
items.Count.ShouldBe(8);
|
items.Count.ShouldBe(8);
|
||||||
@@ -95,7 +95,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 1,
|
Id = 1,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 1
|
CollectionId = 1
|
||||||
},
|
},
|
||||||
[FakeMovie(10)]
|
[FakeMovie(10)]
|
||||||
@@ -106,7 +106,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 2,
|
Id = 2,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 2
|
CollectionId = 2
|
||||||
},
|
},
|
||||||
[FakeMovie(20), FakeMovie(21)]
|
[FakeMovie(20), FakeMovie(21)]
|
||||||
@@ -117,7 +117,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Id = 3,
|
Id = 3,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = true,
|
PlayAll = true,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 3
|
CollectionId = 3
|
||||||
},
|
},
|
||||||
[FakeMovie(30), FakeMovie(31)]
|
[FakeMovie(30), FakeMovie(31)]
|
||||||
@@ -135,11 +135,11 @@ public class PlaylistEnumeratorTests
|
|||||||
var items = new List<int>();
|
var items = new List<int>();
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
|
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
while (enumerator.State.Index > 0)
|
while (enumerator.State.Index > 0)
|
||||||
{
|
{
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
items.Count.ShouldBe(8);
|
items.Count.ShouldBe(8);
|
||||||
@@ -161,7 +161,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Index = 0,
|
Index = 0,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 1
|
CollectionId = 1
|
||||||
},
|
},
|
||||||
[FakeMovie(10)]
|
[FakeMovie(10)]
|
||||||
@@ -173,7 +173,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Index = 1,
|
Index = 1,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = true,
|
PlayAll = true,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 2
|
CollectionId = 2
|
||||||
},
|
},
|
||||||
[FakeMovie(20), FakeMovie(21)]
|
[FakeMovie(20), FakeMovie(21)]
|
||||||
@@ -185,7 +185,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Index = 2,
|
Index = 2,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 3
|
CollectionId = 3
|
||||||
},
|
},
|
||||||
[FakeMovie(30)]
|
[FakeMovie(30)]
|
||||||
@@ -206,7 +206,7 @@ public class PlaylistEnumeratorTests
|
|||||||
for (var i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// with seed 1, shuffle order of (1,2,3) is (2,3,1)
|
// with seed 1, shuffle order of (1,2,3) is (2,3,1)
|
||||||
@@ -231,7 +231,7 @@ public class PlaylistEnumeratorTests
|
|||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
Count = 2,
|
Count = 2,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 1
|
CollectionId = 1
|
||||||
},
|
},
|
||||||
[FakeMovie(10), FakeMovie(11), FakeMovie(12)]
|
[FakeMovie(10), FakeMovie(11), FakeMovie(12)]
|
||||||
@@ -243,7 +243,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Index = 1,
|
Index = 1,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 2
|
CollectionId = 2
|
||||||
},
|
},
|
||||||
[FakeMovie(20)]
|
[FakeMovie(20)]
|
||||||
@@ -255,7 +255,7 @@ public class PlaylistEnumeratorTests
|
|||||||
Index = 2,
|
Index = 2,
|
||||||
PlaybackOrder = PlaybackOrder.Chronological,
|
PlaybackOrder = PlaybackOrder.Chronological,
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
CollectionId = 3
|
CollectionId = 3
|
||||||
},
|
},
|
||||||
[FakeMovie(30)]
|
[FakeMovie(30)]
|
||||||
@@ -276,7 +276,7 @@ public class PlaylistEnumeratorTests
|
|||||||
for (var i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
items.AddRange(enumerator.Current.Map(mi => mi.Id));
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// with seed 1, shuffle order of (1,2,3) is (2,3,1)
|
// with seed 1, shuffle order of (1,2,3) is (2,3,1)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
Collection = collectionOne,
|
Collection = collectionOne,
|
||||||
CollectionId = collectionOne.Id,
|
CollectionId = collectionOne.Id,
|
||||||
StartTime = TimeSpan.FromHours(1),
|
StartTime = TimeSpan.FromHours(1),
|
||||||
@@ -127,7 +127,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
Collection = collectionOne,
|
Collection = collectionOne,
|
||||||
CollectionId = collectionOne.Id,
|
CollectionId = collectionOne.Id,
|
||||||
StartTime = TimeSpan.FromHours(1),
|
StartTime = TimeSpan.FromHours(1),
|
||||||
@@ -199,7 +199,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Index = 1,
|
Index = 1,
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Collection,
|
CollectionType = CollectionType.Collection,
|
||||||
Collection = collectionOne,
|
Collection = collectionOne,
|
||||||
CollectionId = collectionOne.Id,
|
CollectionId = collectionOne.Id,
|
||||||
StartTime = null,
|
StartTime = null,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class RandomizedContentTests
|
|||||||
randomizedContent.Current.IsSome.ShouldBeTrue();
|
randomizedContent.Current.IsSome.ShouldBeTrue();
|
||||||
randomizedContent.Current.Do(c => list.Add(c.Id));
|
randomizedContent.Current.Do(c => list.Add(c.Id));
|
||||||
|
|
||||||
randomizedContent.MoveNext();
|
randomizedContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
@@ -56,7 +56,7 @@ public class RandomizedContentTests
|
|||||||
{
|
{
|
||||||
randomizedContent.State.Index.ShouldBe(i);
|
randomizedContent.State.Index.ShouldBe(i);
|
||||||
|
|
||||||
randomizedContent.MoveNext();
|
randomizedContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public class RandomizedContentTests
|
|||||||
randomizedContent.Current.Map(c => c.Id).IfNone(-1).ShouldBe(_expected[i - 2]);
|
randomizedContent.Current.Map(c => c.Id).IfNone(-1).ShouldBe(_expected[i - 2]);
|
||||||
randomizedContent.State.Index.ShouldBe(i);
|
randomizedContent.State.Index.ShouldBe(i);
|
||||||
|
|
||||||
randomizedContent.MoveNext();
|
randomizedContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ public class ScheduleIntegrationTests
|
|||||||
new ArtistRepository(factory),
|
new ArtistRepository(factory),
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(),
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(),
|
||||||
Substitute.For<ILocalFileSystem>(),
|
Substitute.For<ILocalFileSystem>(),
|
||||||
|
Substitute.For<IRerunHelper>(),
|
||||||
provider.GetRequiredService<ILogger<PlayoutBuilder>>());
|
provider.GetRequiredService<ILogger<PlayoutBuilder>>());
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -320,6 +321,7 @@ public class ScheduleIntegrationTests
|
|||||||
new ArtistRepository(factory),
|
new ArtistRepository(factory),
|
||||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(),
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(),
|
||||||
Substitute.For<ILocalFileSystem>(),
|
Substitute.For<ILocalFileSystem>(),
|
||||||
|
Substitute.For<IRerunHelper>(),
|
||||||
provider.GetRequiredService<ILogger<PlayoutBuilder>>());
|
provider.GetRequiredService<ILogger<PlayoutBuilder>>());
|
||||||
|
|
||||||
for (var i = 0; i <= 24 * 4; i++)
|
for (var i = 0; i <= 24 * 4; i++)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class SeasonEpisodeContentTests
|
|||||||
{
|
{
|
||||||
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
||||||
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public class SeasonEpisodeContentTests
|
|||||||
for (var i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
chronologicalContent.State.Index.ShouldBe(i % 10);
|
chronologicalContent.State.Index.ShouldBe(i % 10);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ public class SeasonEpisodeContentTests
|
|||||||
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
chronologicalContent.Current.IsSome.ShouldBeTrue();
|
||||||
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
chronologicalContent.State.Index.ShouldBe(i - 1);
|
chronologicalContent.State.Index.ShouldBe(i - 1);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ public class SeasonEpisodeContentTests
|
|||||||
for (var i = 0; i < 16; i++)
|
for (var i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
chronologicalContent.State.Index.ShouldBe(i % 8);
|
chronologicalContent.State.Index.ShouldBe(i % 8);
|
||||||
chronologicalContent.MoveNext();
|
chronologicalContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class ShuffledContentTests
|
|||||||
{
|
{
|
||||||
shuffledContent.Current.IsSome.ShouldBeTrue();
|
shuffledContent.Current.IsSome.ShouldBeTrue();
|
||||||
shuffledContent.Current.Do(x => list.Add(x.Id));
|
shuffledContent.Current.Do(x => list.Add(x.Id));
|
||||||
shuffledContent.MoveNext();
|
shuffledContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < list.Count - 1; i++)
|
for (var i = 0; i < list.Count - 1; i++)
|
||||||
@@ -59,7 +59,7 @@ public class ShuffledContentTests
|
|||||||
{
|
{
|
||||||
shuffledContent.Current.IsSome.ShouldBeTrue();
|
shuffledContent.Current.IsSome.ShouldBeTrue();
|
||||||
shuffledContent.Current.Do(x => list.Add(x.Id));
|
shuffledContent.Current.Do(x => list.Add(x.Id));
|
||||||
shuffledContent.MoveNext();
|
shuffledContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.ShouldBe([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
list.ShouldBe([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
||||||
@@ -80,7 +80,7 @@ public class ShuffledContentTests
|
|||||||
{
|
{
|
||||||
shuffledContent.Current.IsSome.ShouldBeTrue();
|
shuffledContent.Current.IsSome.ShouldBeTrue();
|
||||||
shuffledContent.Current.Do(x => list.Add(x.Id));
|
shuffledContent.Current.Do(x => list.Add(x.Id));
|
||||||
shuffledContent.MoveNext();
|
shuffledContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
@@ -99,7 +99,7 @@ public class ShuffledContentTests
|
|||||||
for (var i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
shuffledContent.State.Index.ShouldBe(i);
|
shuffledContent.State.Index.ShouldBe(i);
|
||||||
shuffledContent.MoveNext();
|
shuffledContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ public class ShuffledContentTests
|
|||||||
shuffledContent.Current.IsSome.ShouldBeTrue();
|
shuffledContent.Current.IsSome.ShouldBeTrue();
|
||||||
shuffledContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
shuffledContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i);
|
||||||
shuffledContent.State.Index.ShouldBe(i - 1);
|
shuffledContent.State.Index.ShouldBe(i - 1);
|
||||||
shuffledContent.MoveNext();
|
shuffledContent.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public class PlaylistItem
|
|||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public int PlaylistId { get; set; }
|
public int PlaylistId { get; set; }
|
||||||
public Playlist Playlist { get; set; }
|
public Playlist Playlist { get; set; }
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public int? CollectionId { get; set; }
|
public int? CollectionId { get; set; }
|
||||||
public Collection Collection { get; set; }
|
public Collection Collection { get; set; }
|
||||||
public int? MediaItemId { get; set; }
|
public int? MediaItemId { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Domain;
|
||||||
|
|
||||||
|
[SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix")]
|
||||||
|
public class RerunCollection
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public CollectionType CollectionType { get; set; }
|
||||||
|
public int? CollectionId { get; set; }
|
||||||
|
public Collection Collection { get; set; }
|
||||||
|
public int? MediaItemId { get; set; }
|
||||||
|
public MediaItem MediaItem { get; set; }
|
||||||
|
public int? MultiCollectionId { get; set; }
|
||||||
|
public MultiCollection MultiCollection { get; set; }
|
||||||
|
public int? SmartCollectionId { get; set; }
|
||||||
|
public SmartCollection SmartCollection { get; set; }
|
||||||
|
public PlaybackOrder FirstRunPlaybackOrder { get; set; }
|
||||||
|
public PlaybackOrder RerunPlaybackOrder { get; set; }
|
||||||
|
}
|
||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
namespace ErsatzTV.Core.Domain;
|
namespace ErsatzTV.Core.Domain;
|
||||||
|
|
||||||
public enum ProgramScheduleItemCollectionType
|
public enum CollectionType
|
||||||
{
|
{
|
||||||
Collection = 0,
|
Collection = 0,
|
||||||
TelevisionShow = 1,
|
TelevisionShow = 1,
|
||||||
@@ -9,6 +9,8 @@ public enum ProgramScheduleItemCollectionType
|
|||||||
MultiCollection = 4,
|
MultiCollection = 4,
|
||||||
SmartCollection = 5,
|
SmartCollection = 5,
|
||||||
Playlist = 6,
|
Playlist = 6,
|
||||||
|
RerunFirstRun = 7,
|
||||||
|
RerunRerun = 8,
|
||||||
|
|
||||||
Movie = 10,
|
Movie = 10,
|
||||||
Episode = 20,
|
Episode = 20,
|
||||||
@@ -34,6 +34,7 @@ public class ConfigElementKey
|
|||||||
public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size");
|
public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size");
|
||||||
public static ConfigElementKey MultiCollectionsPageSize => new("pages.multi_collections.page_size");
|
public static ConfigElementKey MultiCollectionsPageSize => new("pages.multi_collections.page_size");
|
||||||
public static ConfigElementKey SmartCollectionsPageSize => new("pages.smart_collections.page_size");
|
public static ConfigElementKey SmartCollectionsPageSize => new("pages.smart_collections.page_size");
|
||||||
|
public static ConfigElementKey RerunCollectionsPageSize => new("pages.rerun_collections.page_size");
|
||||||
public static ConfigElementKey SchedulesPageSize => new("pages.schedules.page_size");
|
public static ConfigElementKey SchedulesPageSize => new("pages.schedules.page_size");
|
||||||
public static ConfigElementKey SchedulesDetailPageSize => new("pages.schedules.detail_page_size");
|
public static ConfigElementKey SchedulesDetailPageSize => new("pages.schedules.detail_page_size");
|
||||||
public static ConfigElementKey PlayoutsPageSize => new("pages.playouts.page_size");
|
public static ConfigElementKey PlayoutsPageSize => new("pages.playouts.page_size");
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class FillerPreset
|
|||||||
public int? Count { get; set; }
|
public int? Count { get; set; }
|
||||||
public int? PadToNearestMinute { get; set; }
|
public int? PadToNearestMinute { get; set; }
|
||||||
public bool AllowWatermarks { get; set; }
|
public bool AllowWatermarks { get; set; }
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public int? CollectionId { get; set; }
|
public int? CollectionId { get; set; }
|
||||||
public Collection Collection { get; set; }
|
public Collection Collection { get; set; }
|
||||||
public int? MediaItemId { get; set; }
|
public int? MediaItemId { get; set; }
|
||||||
|
|||||||
@@ -16,13 +16,15 @@ public class PlayoutProgramScheduleAnchor
|
|||||||
? new DateTimeOffset(AnchorDate.Value, TimeSpan.Zero).ToLocalTime()
|
? new DateTimeOffset(AnchorDate.Value, TimeSpan.Zero).ToLocalTime()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public int? CollectionId { get; set; }
|
public int? CollectionId { get; set; }
|
||||||
public Collection Collection { get; set; }
|
public Collection Collection { get; set; }
|
||||||
public int? MultiCollectionId { get; set; }
|
public int? MultiCollectionId { get; set; }
|
||||||
public MultiCollection MultiCollection { get; set; }
|
public MultiCollection MultiCollection { get; set; }
|
||||||
public int? SmartCollectionId { get; set; }
|
public int? SmartCollectionId { get; set; }
|
||||||
public SmartCollection SmartCollection { get; set; }
|
public SmartCollection SmartCollection { get; set; }
|
||||||
|
public int? RerunCollectionId { get; set; }
|
||||||
|
public RerunCollection RerunCollection { get; set; }
|
||||||
public int? MediaItemId { get; set; }
|
public int? MediaItemId { get; set; }
|
||||||
public MediaItem MediaItem { get; set; }
|
public MediaItem MediaItem { get; set; }
|
||||||
public int? PlaylistId { get; set; }
|
public int? PlaylistId { get; set; }
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public abstract class ProgramScheduleItem
|
|||||||
public StartType StartType => StartTime.HasValue ? StartType.Fixed : StartType.Dynamic;
|
public StartType StartType => StartTime.HasValue ? StartType.Fixed : StartType.Dynamic;
|
||||||
public TimeSpan? StartTime { get; set; }
|
public TimeSpan? StartTime { get; set; }
|
||||||
public FixedStartTimeBehavior? FixedStartTimeBehavior { get; set; }
|
public FixedStartTimeBehavior? FixedStartTimeBehavior { get; set; }
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public GuideMode GuideMode { get; set; }
|
public GuideMode GuideMode { get; set; }
|
||||||
public string CustomTitle { get; set; }
|
public string CustomTitle { get; set; }
|
||||||
public int ProgramScheduleId { get; set; }
|
public int ProgramScheduleId { get; set; }
|
||||||
@@ -27,6 +27,8 @@ public abstract class ProgramScheduleItem
|
|||||||
public MultiCollection MultiCollection { get; set; }
|
public MultiCollection MultiCollection { get; set; }
|
||||||
public int? SmartCollectionId { get; set; }
|
public int? SmartCollectionId { get; set; }
|
||||||
public SmartCollection SmartCollection { get; set; }
|
public SmartCollection SmartCollection { get; set; }
|
||||||
|
public int? RerunCollectionId { get; set; }
|
||||||
|
public RerunCollection RerunCollection { get; set; }
|
||||||
public int? PlaylistId { get; set; }
|
public int? PlaylistId { get; set; }
|
||||||
public Playlist Playlist { get; set; }
|
public Playlist Playlist { get; set; }
|
||||||
public string FakeCollectionKey { get; set; }
|
public string FakeCollectionKey { get; set; }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public class BlockItem
|
|||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public int BlockId { get; set; }
|
public int BlockId { get; set; }
|
||||||
public Block Block { get; set; }
|
public Block Block { get; set; }
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public int? CollectionId { get; set; }
|
public int? CollectionId { get; set; }
|
||||||
public Collection Collection { get; set; }
|
public Collection Collection { get; set; }
|
||||||
public int? MediaItemId { get; set; }
|
public int? MediaItemId { get; set; }
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class Deco
|
|||||||
|
|
||||||
// default filler
|
// default filler
|
||||||
public DecoMode DefaultFillerMode { get; set; }
|
public DecoMode DefaultFillerMode { get; set; }
|
||||||
public ProgramScheduleItemCollectionType DefaultFillerCollectionType { get; set; }
|
public CollectionType DefaultFillerCollectionType { get; set; }
|
||||||
public int? DefaultFillerCollectionId { get; set; }
|
public int? DefaultFillerCollectionId { get; set; }
|
||||||
public Collection DefaultFillerCollection { get; set; }
|
public Collection DefaultFillerCollection { get; set; }
|
||||||
public int? DefaultFillerMediaItemId { get; set; }
|
public int? DefaultFillerMediaItemId { get; set; }
|
||||||
@@ -35,7 +35,7 @@ public class Deco
|
|||||||
|
|
||||||
// dead air fallback
|
// dead air fallback
|
||||||
public DecoMode DeadAirFallbackMode { get; set; }
|
public DecoMode DeadAirFallbackMode { get; set; }
|
||||||
public ProgramScheduleItemCollectionType DeadAirFallbackCollectionType { get; set; }
|
public CollectionType DeadAirFallbackCollectionType { get; set; }
|
||||||
public int? DeadAirFallbackCollectionId { get; set; }
|
public int? DeadAirFallbackCollectionId { get; set; }
|
||||||
public Collection DeadAirFallbackCollection { get; set; }
|
public Collection DeadAirFallbackCollection { get; set; }
|
||||||
public int? DeadAirFallbackMediaItemId { get; set; }
|
public int? DeadAirFallbackMediaItemId { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ErsatzTV.Core.Domain.Scheduling;
|
||||||
|
|
||||||
|
public class RerunHistory
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int PlayoutId { get; set; }
|
||||||
|
public Playout Playout { get; set; }
|
||||||
|
public int RerunCollectionId { get; set; }
|
||||||
|
public RerunCollection RerunCollection { get; set; }
|
||||||
|
public int MediaItemId { get; set; }
|
||||||
|
public MediaItem MediaItem { get; set; }
|
||||||
|
public DateTime When { get; set; }
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ public interface IMediaCollectionRepository
|
|||||||
string query,
|
string query,
|
||||||
string smartCollectionName,
|
string smartCollectionName,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
Task<List<MediaItem>> GetRerunCollectionItems(int id, CancellationToken cancellationToken);
|
||||||
Task<List<MediaItem>> GetShowItemsByShowGuids(List<string> guids);
|
Task<List<MediaItem>> GetShowItemsByShowGuids(List<string> guids);
|
||||||
Task<List<MediaItem>> GetPlaylistItems(int id, CancellationToken cancellationToken);
|
Task<List<MediaItem>> GetPlaylistItems(int id, CancellationToken cancellationToken);
|
||||||
Task<List<Movie>> GetMovie(int id);
|
Task<List<Movie>> GetMovie(int id);
|
||||||
@@ -48,6 +49,7 @@ public interface IMediaCollectionRepository
|
|||||||
Task<List<int>> PlayoutIdsUsingCollection(int collectionId);
|
Task<List<int>> PlayoutIdsUsingCollection(int collectionId);
|
||||||
Task<List<int>> PlayoutIdsUsingMultiCollection(int multiCollectionId);
|
Task<List<int>> PlayoutIdsUsingMultiCollection(int multiCollectionId);
|
||||||
Task<List<int>> PlayoutIdsUsingSmartCollection(int smartCollectionId);
|
Task<List<int>> PlayoutIdsUsingSmartCollection(int smartCollectionId);
|
||||||
|
Task<List<int>> PlayoutIdsUsingRerunCollection(int rerunCollectionId);
|
||||||
Task<bool> IsCustomPlaybackOrder(int collectionId);
|
Task<bool> IsCustomPlaybackOrder(int collectionId);
|
||||||
Task<Option<string>> GetNameFromKey(CollectionKey emptyCollection, CancellationToken cancellationToken);
|
Task<Option<string>> GetNameFromKey(CollectionKey emptyCollection, CancellationToken cancellationToken);
|
||||||
List<CollectionWithItems> GroupIntoFakeCollections(List<MediaItem> items, string fakeKey = null);
|
List<CollectionWithItems> GroupIntoFakeCollections(List<MediaItem> items, string fakeKey = null);
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ public interface IMediaCollectionEnumerator
|
|||||||
int Count { get; }
|
int Count { get; }
|
||||||
Option<TimeSpan> MinimumDuration { get; }
|
Option<TimeSpan> MinimumDuration { get; }
|
||||||
void ResetState(CollectionEnumeratorState state);
|
void ResetState(CollectionEnumeratorState state);
|
||||||
void MoveNext();
|
void MoveNext(Option<DateTimeOffset> scheduledAt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Domain.Scheduling;
|
||||||
|
using ErsatzTV.Core.Scheduling;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Interfaces.Scheduling;
|
||||||
|
|
||||||
|
public interface IRerunHelper
|
||||||
|
{
|
||||||
|
bool ClearHistory { get; set; }
|
||||||
|
|
||||||
|
Task InitWithMediaItems(
|
||||||
|
int playoutId,
|
||||||
|
CollectionKey collectionKey,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
IMediaCollectionEnumerator CreateEnumerator(
|
||||||
|
CollectionKey collectionKey,
|
||||||
|
CollectionEnumeratorState state,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
bool IsFirstRun(CollectionKey collectionKey, int mediaItemId);
|
||||||
|
|
||||||
|
bool IsRerun(CollectionKey collectionKey, int mediaItemId);
|
||||||
|
|
||||||
|
int FirstRunCount(CollectionKey collectionKey);
|
||||||
|
|
||||||
|
int RerunCount(CollectionKey collectionKey);
|
||||||
|
|
||||||
|
void AddToHistory(CollectionKey collectionKey, int mediaItemId, DateTimeOffset scheduledAt);
|
||||||
|
|
||||||
|
System.Collections.Generic.HashSet<int> GetHistoryToRemove();
|
||||||
|
|
||||||
|
List<RerunHistory> GetHistoryToAdd();
|
||||||
|
}
|
||||||
@@ -242,7 +242,7 @@ public class BlockPlayoutBuilder(
|
|||||||
result.AddedHistory.Add(nextHistory);
|
result.AddedHistory.Add(nextHistory);
|
||||||
|
|
||||||
currentTime += itemDuration;
|
currentTime += itemDuration;
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pastTime)
|
if (pastTime)
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public class BlockPlayoutFillerBuilder(
|
|||||||
result.AddedHistory.Add(nextHistory);
|
result.AddedHistory.Add(nextHistory);
|
||||||
|
|
||||||
current += itemDuration;
|
current += itemDuration;
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(filler.StartOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pastTime)
|
if (pastTime)
|
||||||
@@ -227,17 +227,17 @@ public class BlockPlayoutFillerBuilder(
|
|||||||
{
|
{
|
||||||
switch (deco.DefaultFillerCollectionType)
|
switch (deco.DefaultFillerCollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
return deco.DefaultFillerCollectionId.HasValue;
|
return deco.DefaultFillerCollectionId.HasValue;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionShow:
|
case CollectionType.TelevisionShow:
|
||||||
return deco.DefaultFillerMediaItemId.HasValue;
|
return deco.DefaultFillerMediaItemId.HasValue;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionSeason:
|
case CollectionType.TelevisionSeason:
|
||||||
return deco.DefaultFillerMediaItemId.HasValue;
|
return deco.DefaultFillerMediaItemId.HasValue;
|
||||||
case ProgramScheduleItemCollectionType.Artist:
|
case CollectionType.Artist:
|
||||||
return deco.DefaultFillerMediaItemId.HasValue;
|
return deco.DefaultFillerMediaItemId.HasValue;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
return deco.DefaultFillerMultiCollectionId.HasValue;
|
return deco.DefaultFillerMultiCollectionId.HasValue;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
return deco.DefaultFillerSmartCollectionId.HasValue;
|
return deco.DefaultFillerSmartCollectionId.HasValue;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ public class BlockPlayoutShuffledMediaCollectionEnumerator : IMediaCollectionEnu
|
|||||||
public Option<MediaItem> Current => _shuffled.Any() ? _shuffled[State.Index % _mediaItemCount] : None;
|
public Option<MediaItem> Current => _shuffled.Any() ? _shuffled[State.Index % _mediaItemCount] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext()
|
public void MoveNext(Option<DateTimeOffset> scheduledAt)
|
||||||
{
|
{
|
||||||
State.Index++;
|
State.Index++;
|
||||||
if (State.Index % _mediaItemCount == 0)
|
if (State.Index % _mediaItemCount == 0)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public sealed class ChronologicalMediaCollectionEnumerator : IMediaCollectionEnu
|
|||||||
|
|
||||||
while (State.Index < state.Index)
|
while (State.Index < state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,8 @@ public sealed class ChronologicalMediaCollectionEnumerator : IMediaCollectionEnu
|
|||||||
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count;
|
public void MoveNext(Option<DateTimeOffset> scheduledAt) =>
|
||||||
|
State.Index = (State.Index + 1) % _sortedMediaItems.Count;
|
||||||
|
|
||||||
public Option<TimeSpan> MinimumDuration => _lazyMinimumDuration.Value;
|
public Option<TimeSpan> MinimumDuration => _lazyMinimumDuration.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ namespace ErsatzTV.Core.Scheduling;
|
|||||||
|
|
||||||
public class CollectionKey : Record<CollectionKey>
|
public class CollectionKey : Record<CollectionKey>
|
||||||
{
|
{
|
||||||
public ProgramScheduleItemCollectionType CollectionType { get; set; }
|
public CollectionType CollectionType { get; set; }
|
||||||
public int? CollectionId { get; set; }
|
public int? CollectionId { get; set; }
|
||||||
public int? MultiCollectionId { get; set; }
|
public int? MultiCollectionId { get; set; }
|
||||||
public int? SmartCollectionId { get; set; }
|
public int? SmartCollectionId { get; set; }
|
||||||
|
public int? RerunCollectionId { get; set; }
|
||||||
public int? MediaItemId { get; set; }
|
public int? MediaItemId { get; set; }
|
||||||
public int? PlaylistId { get; set; }
|
public int? PlaylistId { get; set; }
|
||||||
public string FakeCollectionKey { get; set; }
|
public string FakeCollectionKey { get; set; }
|
||||||
@@ -17,71 +18,71 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
public static CollectionKey ForPlaylistItem(PlaylistItem item) =>
|
public static CollectionKey ForPlaylistItem(PlaylistItem item) =>
|
||||||
item.CollectionType switch
|
item.CollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => new CollectionKey
|
CollectionType.Collection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
CollectionId = item.CollectionId
|
CollectionId = item.CollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
|
CollectionType.TelevisionShow => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
|
CollectionType.TelevisionSeason => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Artist => new CollectionKey
|
CollectionType.Artist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MultiCollection => new CollectionKey
|
CollectionType.MultiCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MultiCollectionId = item.MultiCollectionId
|
MultiCollectionId = item.MultiCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.SmartCollection => new CollectionKey
|
CollectionType.SmartCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
SmartCollectionId = item.SmartCollectionId
|
SmartCollectionId = item.SmartCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.FakeCollection => new CollectionKey
|
CollectionType.FakeCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType
|
CollectionType = item.CollectionType
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.FakePlaylistItem => new CollectionKey
|
CollectionType.FakePlaylistItem => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
CollectionId = item.CollectionId
|
CollectionId = item.CollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Movie => new CollectionKey
|
CollectionType.Movie => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Episode => new CollectionKey
|
CollectionType.Episode => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MusicVideo => new CollectionKey
|
CollectionType.MusicVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.OtherVideo => new CollectionKey
|
CollectionType.OtherVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Song => new CollectionKey
|
CollectionType.Song => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Image => new CollectionKey
|
CollectionType.Image => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
@@ -92,66 +93,66 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
public static CollectionKey ForBlockItem(BlockItem item) =>
|
public static CollectionKey ForBlockItem(BlockItem item) =>
|
||||||
item.CollectionType switch
|
item.CollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => new CollectionKey
|
CollectionType.Collection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
CollectionId = item.CollectionId
|
CollectionId = item.CollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
|
CollectionType.TelevisionShow => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
|
CollectionType.TelevisionSeason => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Artist => new CollectionKey
|
CollectionType.Artist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MultiCollection => new CollectionKey
|
CollectionType.MultiCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MultiCollectionId = item.MultiCollectionId
|
MultiCollectionId = item.MultiCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.SmartCollection => new CollectionKey
|
CollectionType.SmartCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
SmartCollectionId = item.SmartCollectionId
|
SmartCollectionId = item.SmartCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.FakeCollection => new CollectionKey
|
CollectionType.FakeCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType
|
CollectionType = item.CollectionType
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Movie => new CollectionKey
|
CollectionType.Movie => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Episode => new CollectionKey
|
CollectionType.Episode => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MusicVideo => new CollectionKey
|
CollectionType.MusicVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.OtherVideo => new CollectionKey
|
CollectionType.OtherVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Song => new CollectionKey
|
CollectionType.Song => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Image => new CollectionKey
|
CollectionType.Image => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId
|
MediaItemId = item.MediaItemId
|
||||||
@@ -162,66 +163,66 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
public static CollectionKey ForDecoDefaultFiller(Deco deco) =>
|
public static CollectionKey ForDecoDefaultFiller(Deco deco) =>
|
||||||
deco.DefaultFillerCollectionType switch
|
deco.DefaultFillerCollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => new CollectionKey
|
CollectionType.Collection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
CollectionId = deco.DefaultFillerCollectionId
|
CollectionId = deco.DefaultFillerCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
|
CollectionType.TelevisionShow => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
|
CollectionType.TelevisionSeason => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Artist => new CollectionKey
|
CollectionType.Artist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MultiCollection => new CollectionKey
|
CollectionType.MultiCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MultiCollectionId = deco.DefaultFillerMultiCollectionId
|
MultiCollectionId = deco.DefaultFillerMultiCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.SmartCollection => new CollectionKey
|
CollectionType.SmartCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
SmartCollectionId = deco.DefaultFillerSmartCollectionId
|
SmartCollectionId = deco.DefaultFillerSmartCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.FakeCollection => new CollectionKey
|
CollectionType.FakeCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType
|
CollectionType = deco.DefaultFillerCollectionType
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Movie => new CollectionKey
|
CollectionType.Movie => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Episode => new CollectionKey
|
CollectionType.Episode => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MusicVideo => new CollectionKey
|
CollectionType.MusicVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.OtherVideo => new CollectionKey
|
CollectionType.OtherVideo => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Song => new CollectionKey
|
CollectionType.Song => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Image => new CollectionKey
|
CollectionType.Image => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = deco.DefaultFillerCollectionType,
|
CollectionType = deco.DefaultFillerCollectionType,
|
||||||
MediaItemId = deco.DefaultFillerMediaItemId
|
MediaItemId = deco.DefaultFillerMediaItemId
|
||||||
@@ -232,49 +233,61 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
public static CollectionKey ForScheduleItem(ProgramScheduleItem item) =>
|
public static CollectionKey ForScheduleItem(ProgramScheduleItem item) =>
|
||||||
item.CollectionType switch
|
item.CollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => new CollectionKey
|
CollectionType.Collection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
CollectionId = item.CollectionId,
|
CollectionId = item.CollectionId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
|
CollectionType.TelevisionShow => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
|
CollectionType.TelevisionSeason => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Artist => new CollectionKey
|
CollectionType.Artist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MediaItemId = item.MediaItemId,
|
MediaItemId = item.MediaItemId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MultiCollection => new CollectionKey
|
CollectionType.MultiCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
MultiCollectionId = item.MultiCollectionId,
|
MultiCollectionId = item.MultiCollectionId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.SmartCollection => new CollectionKey
|
CollectionType.SmartCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
SmartCollectionId = item.SmartCollectionId,
|
SmartCollectionId = item.SmartCollectionId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Playlist => new CollectionKey
|
CollectionType.RerunFirstRun => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
|
},
|
||||||
|
CollectionType.RerunRerun => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
RerunCollectionId = item.RerunCollectionId,
|
||||||
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
|
},
|
||||||
|
CollectionType.Playlist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
PlaylistId = item.PlaylistId,
|
PlaylistId = item.PlaylistId,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.FakeCollection => new CollectionKey
|
CollectionType.FakeCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = item.CollectionType,
|
CollectionType = item.CollectionType,
|
||||||
FakeCollectionKey = item.FakeCollectionKey
|
FakeCollectionKey = item.FakeCollectionKey
|
||||||
@@ -285,37 +298,37 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
public static CollectionKey ForFillerPreset(FillerPreset filler) =>
|
public static CollectionKey ForFillerPreset(FillerPreset filler) =>
|
||||||
filler.CollectionType switch
|
filler.CollectionType switch
|
||||||
{
|
{
|
||||||
ProgramScheduleItemCollectionType.Collection => new CollectionKey
|
CollectionType.Collection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
CollectionId = filler.CollectionId
|
CollectionId = filler.CollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
|
CollectionType.TelevisionShow => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
MediaItemId = filler.MediaItemId
|
MediaItemId = filler.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
|
CollectionType.TelevisionSeason => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
MediaItemId = filler.MediaItemId
|
MediaItemId = filler.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Artist => new CollectionKey
|
CollectionType.Artist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
MediaItemId = filler.MediaItemId
|
MediaItemId = filler.MediaItemId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.MultiCollection => new CollectionKey
|
CollectionType.MultiCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
MultiCollectionId = filler.MultiCollectionId
|
MultiCollectionId = filler.MultiCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.SmartCollection => new CollectionKey
|
CollectionType.SmartCollection => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
SmartCollectionId = filler.SmartCollectionId
|
SmartCollectionId = filler.SmartCollectionId
|
||||||
},
|
},
|
||||||
ProgramScheduleItemCollectionType.Playlist => new CollectionKey
|
CollectionType.Playlist => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = filler.CollectionType,
|
CollectionType = filler.CollectionType,
|
||||||
PlaylistId = filler.PlaylistId
|
PlaylistId = filler.PlaylistId
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator
|
|||||||
State = new CollectionEnumeratorState { Seed = state.Seed };
|
State = new CollectionEnumeratorState { Seed = state.Seed };
|
||||||
while (State.Index < state.Index)
|
while (State.Index < state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,8 @@ public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator
|
|||||||
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count;
|
public void MoveNext(Option<DateTimeOffset> scheduledAt) =>
|
||||||
|
State.Index = (State.Index + 1) % _sortedMediaItems.Count;
|
||||||
|
|
||||||
public Option<TimeSpan> MinimumDuration => _lazyMinimumDuration.Value;
|
public Option<TimeSpan> MinimumDuration => _lazyMinimumDuration.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -138,55 +138,55 @@ public class MarathonHelper(IMediaCollectionRepository mediaCollectionRepository
|
|||||||
mediaItem switch
|
mediaItem switch
|
||||||
{
|
{
|
||||||
Episode e => new GroupKey(
|
Episode e => new GroupKey(
|
||||||
ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType.TelevisionShow,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
e.Season?.ShowId ?? 0),
|
e.Season?.ShowId ?? 0),
|
||||||
_ => new GroupKey(ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, 0)
|
_ => new GroupKey(CollectionType.TelevisionShow, null, null, null, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static GroupKey MediaItemKeyBySeason(MediaItem mediaItem) =>
|
private static GroupKey MediaItemKeyBySeason(MediaItem mediaItem) =>
|
||||||
mediaItem switch
|
mediaItem switch
|
||||||
{
|
{
|
||||||
Episode e => new GroupKey(
|
Episode e => new GroupKey(
|
||||||
ProgramScheduleItemCollectionType.TelevisionSeason,
|
CollectionType.TelevisionSeason,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
e.SeasonId),
|
e.SeasonId),
|
||||||
_ => new GroupKey(ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, 0)
|
_ => new GroupKey(CollectionType.TelevisionSeason, null, null, null, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static GroupKey MediaItemKeyByArtist(MediaItem mediaItem) =>
|
private static GroupKey MediaItemKeyByArtist(MediaItem mediaItem) =>
|
||||||
mediaItem switch
|
mediaItem switch
|
||||||
{
|
{
|
||||||
MusicVideo mv => new GroupKey(
|
MusicVideo mv => new GroupKey(
|
||||||
ProgramScheduleItemCollectionType.Artist,
|
CollectionType.Artist,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
mv.ArtistId),
|
mv.ArtistId),
|
||||||
_ => new GroupKey(ProgramScheduleItemCollectionType.Artist, null, null, null, 0)
|
_ => new GroupKey(CollectionType.Artist, null, null, null, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static GroupKey MediaItemKeyByAlbum(MediaItem mediaItem) =>
|
private static GroupKey MediaItemKeyByAlbum(MediaItem mediaItem) =>
|
||||||
mediaItem switch
|
mediaItem switch
|
||||||
{
|
{
|
||||||
Song s => new GroupKey(
|
Song s => new GroupKey(
|
||||||
ProgramScheduleItemCollectionType.Collection,
|
CollectionType.Collection,
|
||||||
s.SongMetadata.HeadOrNone().Map(sm => sm.Album.GetStableHashCode()).IfNone(0),
|
s.SongMetadata.HeadOrNone().Map(sm => sm.Album.GetStableHashCode()).IfNone(0),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null),
|
null),
|
||||||
MusicVideo mv => new GroupKey(
|
MusicVideo mv => new GroupKey(
|
||||||
ProgramScheduleItemCollectionType.Collection,
|
CollectionType.Collection,
|
||||||
mv.MusicVideoMetadata.HeadOrNone()
|
mv.MusicVideoMetadata.HeadOrNone()
|
||||||
.Map(mvm => $"{mv.ArtistId}-${mvm.Album}".GetStableHashCode()).IfNone(0),
|
.Map(mvm => $"{mv.ArtistId}-${mvm.Album}".GetStableHashCode()).IfNone(0),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null),
|
null),
|
||||||
_ => new GroupKey(ProgramScheduleItemCollectionType.Collection, 0, null, null, null)
|
_ => new GroupKey(CollectionType.Collection, 0, null, null, null)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static PlaylistItem GroupToPlaylistItem(
|
private static PlaylistItem GroupToPlaylistItem(
|
||||||
@@ -211,7 +211,7 @@ public class MarathonHelper(IMediaCollectionRepository mediaCollectionRepository
|
|||||||
};
|
};
|
||||||
|
|
||||||
private record GroupKey(
|
private record GroupKey(
|
||||||
ProgramScheduleItemCollectionType CollectionType,
|
CollectionType CollectionType,
|
||||||
int? CollectionId,
|
int? CollectionId,
|
||||||
int? MultiCollectionId,
|
int? MultiCollectionId,
|
||||||
int? SmartCollectionId,
|
int? SmartCollectionId,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class PlaylistHelper(IMediaCollectionRepository mediaCollectionRepository
|
|||||||
{
|
{
|
||||||
Index = playlistIndex,
|
Index = playlistIndex,
|
||||||
|
|
||||||
CollectionType = ProgramScheduleItemCollectionType.FakePlaylistItem,
|
CollectionType = CollectionType.FakePlaylistItem,
|
||||||
CollectionId = playlistIndex,
|
CollectionId = playlistIndex,
|
||||||
|
|
||||||
PlayAll = false,
|
PlayAll = false,
|
||||||
|
|||||||
@@ -779,13 +779,13 @@ public class SchedulingEngine(
|
|||||||
remainingToFill -= itemDuration;
|
remainingToFill -= itemDuration;
|
||||||
_state.CurrentTime += itemDuration;
|
_state.CurrentTime += itemDuration;
|
||||||
|
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
else if (discardAttempts > 0)
|
else if (discardAttempts > 0)
|
||||||
{
|
{
|
||||||
// item won't fit; try the next one
|
// item won't fit; try the next one
|
||||||
discardAttempts--;
|
discardAttempts--;
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
else if (trim)
|
else if (trim)
|
||||||
{
|
{
|
||||||
@@ -806,7 +806,7 @@ public class SchedulingEngine(
|
|||||||
remainingToFill = TimeSpan.Zero;
|
remainingToFill = TimeSpan.Zero;
|
||||||
_state.CurrentTime = targetTime;
|
_state.CurrentTime = targetTime;
|
||||||
|
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
else if (maybeFallbackEnumeratorDetails.IsSome)
|
else if (maybeFallbackEnumeratorDetails.IsSome)
|
||||||
{
|
{
|
||||||
@@ -836,7 +836,7 @@ public class SchedulingEngine(
|
|||||||
_state.AddedHistory.Add(history);
|
_state.AddedHistory.Add(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackEnumeratorDetails.Enumerator.MoveNext();
|
fallbackEnumeratorDetails.Enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -959,7 +959,7 @@ public class SchedulingEngine(
|
|||||||
_state.AddedHistory.Add(history);
|
_state.AddedHistory.Add(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -1077,7 +1077,7 @@ public class SchedulingEngine(
|
|||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1115,7 +1115,7 @@ public class SchedulingEngine(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enumeratorDetails.Enumerator.MoveNext();
|
enumeratorDetails.Enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1312,7 +1312,7 @@ public class SchedulingEngine(
|
|||||||
|
|
||||||
// only move next at the end, because that may also move
|
// only move next at the end, because that may also move
|
||||||
// the enumerator index
|
// the enumerator index
|
||||||
playlistEnumerator.MoveNext();
|
playlistEnumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ internal static class HistoryDetails
|
|||||||
|
|
||||||
if (!current)
|
if (!current)
|
||||||
{
|
{
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,77 +18,83 @@ public static class MediaItemsForCollection
|
|||||||
|
|
||||||
switch (collectionKey.CollectionType)
|
switch (collectionKey.CollectionType)
|
||||||
{
|
{
|
||||||
case ProgramScheduleItemCollectionType.Collection:
|
case CollectionType.Collection:
|
||||||
result.AddRange(await mediaCollectionRepository.GetItems(collectionKey.CollectionId ?? 0));
|
result.AddRange(await mediaCollectionRepository.GetItems(collectionKey.CollectionId ?? 0));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionShow:
|
case CollectionType.TelevisionShow:
|
||||||
result.AddRange(await televisionRepository.GetShowItems(collectionKey.MediaItemId ?? 0));
|
result.AddRange(await televisionRepository.GetShowItems(collectionKey.MediaItemId ?? 0));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.TelevisionSeason:
|
case CollectionType.TelevisionSeason:
|
||||||
result.AddRange(await televisionRepository.GetSeasonItems(collectionKey.MediaItemId ?? 0));
|
result.AddRange(await televisionRepository.GetSeasonItems(collectionKey.MediaItemId ?? 0));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Artist:
|
case CollectionType.Artist:
|
||||||
result.AddRange(await artistRepository.GetArtistItems(collectionKey.MediaItemId ?? 0));
|
result.AddRange(await artistRepository.GetArtistItems(collectionKey.MediaItemId ?? 0));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MultiCollection:
|
case CollectionType.MultiCollection:
|
||||||
result.AddRange(
|
result.AddRange(
|
||||||
await mediaCollectionRepository.GetMultiCollectionItems(
|
await mediaCollectionRepository.GetMultiCollectionItems(
|
||||||
collectionKey.MultiCollectionId ?? 0,
|
collectionKey.MultiCollectionId ?? 0,
|
||||||
cancellationToken));
|
cancellationToken));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.SmartCollection:
|
case CollectionType.SmartCollection:
|
||||||
result.AddRange(
|
result.AddRange(
|
||||||
await mediaCollectionRepository.GetSmartCollectionItems(
|
await mediaCollectionRepository.GetSmartCollectionItems(
|
||||||
collectionKey.SmartCollectionId ?? 0,
|
collectionKey.SmartCollectionId ?? 0,
|
||||||
cancellationToken));
|
cancellationToken));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Playlist:
|
case CollectionType.RerunFirstRun or CollectionType.RerunRerun:
|
||||||
|
result.AddRange(
|
||||||
|
await mediaCollectionRepository.GetRerunCollectionItems(
|
||||||
|
collectionKey.RerunCollectionId ?? 0,
|
||||||
|
cancellationToken));
|
||||||
|
break;
|
||||||
|
case CollectionType.Playlist:
|
||||||
result.AddRange(
|
result.AddRange(
|
||||||
await mediaCollectionRepository.GetPlaylistItems(collectionKey.PlaylistId ?? 0, cancellationToken));
|
await mediaCollectionRepository.GetPlaylistItems(collectionKey.PlaylistId ?? 0, cancellationToken));
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Movie:
|
case CollectionType.Movie:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetMovie(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetMovie(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Episode:
|
case CollectionType.Episode:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetEpisode(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetEpisode(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.MusicVideo:
|
case CollectionType.MusicVideo:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetMusicVideo(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetMusicVideo(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.OtherVideo:
|
case CollectionType.OtherVideo:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetOtherVideo(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetOtherVideo(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Song:
|
case CollectionType.Song:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetSong(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetSong(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.Image:
|
case CollectionType.Image:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetImage(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetImage(mediaItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ProgramScheduleItemCollectionType.RemoteStream:
|
case CollectionType.RemoteStream:
|
||||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
{
|
{
|
||||||
result.AddRange(await mediaCollectionRepository.GetRemoteStream(mediaItemId));
|
result.AddRange(await mediaCollectionRepository.GetRemoteStream(mediaItemId));
|
||||||
|
|||||||
@@ -58,14 +58,14 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator
|
|||||||
|
|
||||||
public Option<TimeSpan> MinimumDuration { get; private set; }
|
public Option<TimeSpan> MinimumDuration { get; private set; }
|
||||||
|
|
||||||
public void MoveNext()
|
public void MoveNext(Option<DateTimeOffset> scheduledAt)
|
||||||
{
|
{
|
||||||
foreach (MediaItem maybeMediaItem in _sortedEnumerators[EnumeratorIndex].Enumerator.Current)
|
foreach (MediaItem maybeMediaItem in _sortedEnumerators[EnumeratorIndex].Enumerator.Current)
|
||||||
{
|
{
|
||||||
_remainingMediaItemIds.Remove(maybeMediaItem.Id);
|
_remainingMediaItemIds.Remove(maybeMediaItem.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sortedEnumerators[EnumeratorIndex].Enumerator.MoveNext();
|
_sortedEnumerators[EnumeratorIndex].Enumerator.MoveNext(scheduledAt);
|
||||||
_itemsTakenFromCurrent++;
|
_itemsTakenFromCurrent++;
|
||||||
|
|
||||||
bool shouldSwitchEnumerator = _batchSize.Match(
|
bool shouldSwitchEnumerator = _batchSize.Match(
|
||||||
@@ -238,7 +238,7 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator
|
|||||||
|
|
||||||
while (result.State.Index < state.Index)
|
while (result.State.Index < state.Index)
|
||||||
{
|
{
|
||||||
result.MoveNext();
|
result.MoveNext(Option<DateTimeOffset>.None);
|
||||||
|
|
||||||
// previous state is no longer valid; playlist now has fewer items
|
// previous state is no longer valid; playlist now has fewer items
|
||||||
if (result.State.Index == 0)
|
if (result.State.Index == 0)
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ public record PlayoutBuildResult(
|
|||||||
System.Collections.Generic.HashSet<int> ItemsToRemove,
|
System.Collections.Generic.HashSet<int> ItemsToRemove,
|
||||||
List<PlayoutHistory> AddedHistory,
|
List<PlayoutHistory> AddedHistory,
|
||||||
System.Collections.Generic.HashSet<int> HistoryToRemove,
|
System.Collections.Generic.HashSet<int> HistoryToRemove,
|
||||||
|
List<RerunHistory> AddedRerunHistory,
|
||||||
|
System.Collections.Generic.HashSet<int> RerunHistoryToRemove,
|
||||||
Option<DateTimeOffset> TimeShiftTo)
|
Option<DateTimeOffset> TimeShiftTo)
|
||||||
{
|
{
|
||||||
public static PlayoutBuildResult Empty =>
|
public static PlayoutBuildResult Empty =>
|
||||||
@@ -22,5 +24,7 @@ public record PlayoutBuildResult(
|
|||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
|
[],
|
||||||
|
[],
|
||||||
Option<DateTimeOffset>.None);
|
Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
private readonly IArtistRepository _artistRepository;
|
private readonly IArtistRepository _artistRepository;
|
||||||
private readonly IConfigElementRepository _configElementRepository;
|
private readonly IConfigElementRepository _configElementRepository;
|
||||||
private readonly ILocalFileSystem _localFileSystem;
|
private readonly ILocalFileSystem _localFileSystem;
|
||||||
|
private readonly IRerunHelper _rerunHelper;
|
||||||
private readonly IMediaCollectionRepository _mediaCollectionRepository;
|
private readonly IMediaCollectionRepository _mediaCollectionRepository;
|
||||||
private readonly IMultiEpisodeShuffleCollectionEnumeratorFactory _multiEpisodeFactory;
|
private readonly IMultiEpisodeShuffleCollectionEnumeratorFactory _multiEpisodeFactory;
|
||||||
private readonly ITelevisionRepository _televisionRepository;
|
private readonly ITelevisionRepository _televisionRepository;
|
||||||
@@ -34,6 +35,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
IArtistRepository artistRepository,
|
IArtistRepository artistRepository,
|
||||||
IMultiEpisodeShuffleCollectionEnumeratorFactory multiEpisodeFactory,
|
IMultiEpisodeShuffleCollectionEnumeratorFactory multiEpisodeFactory,
|
||||||
ILocalFileSystem localFileSystem,
|
ILocalFileSystem localFileSystem,
|
||||||
|
IRerunHelper rerunHelper,
|
||||||
ILogger<PlayoutBuilder> logger)
|
ILogger<PlayoutBuilder> logger)
|
||||||
{
|
{
|
||||||
_configElementRepository = configElementRepository;
|
_configElementRepository = configElementRepository;
|
||||||
@@ -42,6 +44,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
_artistRepository = artistRepository;
|
_artistRepository = artistRepository;
|
||||||
_multiEpisodeFactory = multiEpisodeFactory;
|
_multiEpisodeFactory = multiEpisodeFactory;
|
||||||
_localFileSystem = localFileSystem;
|
_localFileSystem = localFileSystem;
|
||||||
|
_rerunHelper = rerunHelper;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +92,12 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
result = await Build(playout, referenceData, result, mode, parameters, cancellationToken);
|
result = await Build(playout, referenceData, result, mode, parameters, cancellationToken);
|
||||||
|
|
||||||
|
result = result with
|
||||||
|
{
|
||||||
|
RerunHistoryToRemove = _rerunHelper.GetHistoryToRemove(),
|
||||||
|
AddedRerunHistory = _rerunHelper.GetHistoryToAdd()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -181,6 +190,9 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
var smartCollectionIds =
|
var smartCollectionIds =
|
||||||
playout.ProgramScheduleAnchors.Map(a => Optional(a.SmartCollectionId)).Somes().ToHashSet();
|
playout.ProgramScheduleAnchors.Map(a => Optional(a.SmartCollectionId)).Somes().ToHashSet();
|
||||||
|
|
||||||
|
var rerunCollectionIds =
|
||||||
|
playout.ProgramScheduleAnchors.Map(a => Optional(a.RerunCollectionId)).Somes().ToHashSet();
|
||||||
|
|
||||||
var mediaItemIds = playout.ProgramScheduleAnchors.Map(a => Optional(a.MediaItemId)).Somes().ToHashSet();
|
var mediaItemIds = playout.ProgramScheduleAnchors.Map(a => Optional(a.MediaItemId)).Somes().ToHashSet();
|
||||||
|
|
||||||
playout.ProgramScheduleAnchors.Clear();
|
playout.ProgramScheduleAnchors.Clear();
|
||||||
@@ -206,6 +218,13 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
playout.ProgramScheduleAnchors.Add(minAnchor);
|
playout.ProgramScheduleAnchors.Add(minAnchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (int rerunCollectionId in rerunCollectionIds)
|
||||||
|
{
|
||||||
|
PlayoutProgramScheduleAnchor minAnchor = allAnchors.Filter(a => a.RerunCollectionId == rerunCollectionId)
|
||||||
|
.MinBy(a => a.AnchorDateOffset.IfNone(DateTimeOffset.MaxValue).Ticks);
|
||||||
|
playout.ProgramScheduleAnchors.Add(minAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (int mediaItemId in mediaItemIds)
|
foreach (int mediaItemId in mediaItemIds)
|
||||||
{
|
{
|
||||||
PlayoutProgramScheduleAnchor minAnchor = allAnchors.Filter(a => a.MediaItemId == mediaItemId)
|
PlayoutProgramScheduleAnchor minAnchor = allAnchors.Filter(a => a.MediaItemId == mediaItemId)
|
||||||
@@ -261,6 +280,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
referenceData.Channel.Name);
|
referenceData.Channel.Name);
|
||||||
|
|
||||||
result = result with { ClearItems = true };
|
result = result with { ClearItems = true };
|
||||||
|
_rerunHelper.ClearHistory = true;
|
||||||
playout.Anchor = null;
|
playout.Anchor = null;
|
||||||
playout.ProgramScheduleAnchors.Clear();
|
playout.ProgramScheduleAnchors.Clear();
|
||||||
playout.OnDemandCheckpoint = null;
|
playout.OnDemandCheckpoint = null;
|
||||||
@@ -610,19 +630,19 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
{
|
{
|
||||||
var (showId, _, _) when showId > 0 => new CollectionKey
|
var (showId, _, _) when showId > 0 => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
CollectionType = CollectionType.TelevisionShow,
|
||||||
MediaItemId = showId,
|
MediaItemId = showId,
|
||||||
FakeCollectionKey = collectionKeyString
|
FakeCollectionKey = collectionKeyString
|
||||||
},
|
},
|
||||||
var (_, artistId, _) when artistId > 0 => new CollectionKey
|
var (_, artistId, _) when artistId > 0 => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = ProgramScheduleItemCollectionType.Artist,
|
CollectionType = CollectionType.Artist,
|
||||||
MediaItemId = artistId,
|
MediaItemId = artistId,
|
||||||
FakeCollectionKey = collectionKeyString
|
FakeCollectionKey = collectionKeyString
|
||||||
},
|
},
|
||||||
var (_, _, k) when k is not null => new CollectionKey
|
var (_, _, k) when k is not null => new CollectionKey
|
||||||
{
|
{
|
||||||
CollectionType = ProgramScheduleItemCollectionType.FakeCollection,
|
CollectionType = CollectionType.FakeCollection,
|
||||||
FakeCollectionKey = collectionKeyString
|
FakeCollectionKey = collectionKeyString
|
||||||
},
|
},
|
||||||
var (_, _, _) => null
|
var (_, _, _) => null
|
||||||
@@ -1145,6 +1165,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
&& a.MediaItemId == collectionKey.MediaItemId
|
&& a.MediaItemId == collectionKey.MediaItemId
|
||||||
&& a.FakeCollectionKey == collectionKey.FakeCollectionKey
|
&& a.FakeCollectionKey == collectionKey.FakeCollectionKey
|
||||||
&& a.SmartCollectionId == collectionKey.SmartCollectionId
|
&& a.SmartCollectionId == collectionKey.SmartCollectionId
|
||||||
|
&& a.RerunCollectionId == collectionKey.RerunCollectionId
|
||||||
&& a.MultiCollectionId == collectionKey.MultiCollectionId
|
&& a.MultiCollectionId == collectionKey.MultiCollectionId
|
||||||
&& a.PlaylistId == collectionKey.PlaylistId
|
&& a.PlaylistId == collectionKey.PlaylistId
|
||||||
&& a.AnchorDate is null);
|
&& a.AnchorDate is null);
|
||||||
@@ -1165,6 +1186,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
CollectionId = collectionKey.CollectionId,
|
CollectionId = collectionKey.CollectionId,
|
||||||
MultiCollectionId = collectionKey.MultiCollectionId,
|
MultiCollectionId = collectionKey.MultiCollectionId,
|
||||||
SmartCollectionId = collectionKey.SmartCollectionId,
|
SmartCollectionId = collectionKey.SmartCollectionId,
|
||||||
|
RerunCollectionId = collectionKey.RerunCollectionId,
|
||||||
MediaItemId = collectionKey.MediaItemId,
|
MediaItemId = collectionKey.MediaItemId,
|
||||||
PlaylistId = collectionKey.PlaylistId,
|
PlaylistId = collectionKey.PlaylistId,
|
||||||
FakeCollectionKey = collectionKey.FakeCollectionKey,
|
FakeCollectionKey = collectionKey.FakeCollectionKey,
|
||||||
@@ -1207,6 +1229,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
&& a.CollectionId == collectionKey.CollectionId
|
&& a.CollectionId == collectionKey.CollectionId
|
||||||
&& a.MultiCollectionId == collectionKey.MultiCollectionId
|
&& a.MultiCollectionId == collectionKey.MultiCollectionId
|
||||||
&& a.SmartCollectionId == collectionKey.SmartCollectionId
|
&& a.SmartCollectionId == collectionKey.SmartCollectionId
|
||||||
|
&& a.RerunCollectionId == collectionKey.RerunCollectionId
|
||||||
&& a.MediaItemId == collectionKey.MediaItemId
|
&& a.MediaItemId == collectionKey.MediaItemId
|
||||||
&& a.PlaylistId == collectionKey.PlaylistId);
|
&& a.PlaylistId == collectionKey.PlaylistId);
|
||||||
|
|
||||||
@@ -1223,7 +1246,13 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
|
|
||||||
state ??= new CollectionEnumeratorState { Seed = Random.Next(), Index = 0 };
|
state ??= new CollectionEnumeratorState { Seed = Random.Next(), Index = 0 };
|
||||||
|
|
||||||
if (collectionKey.CollectionType is ProgramScheduleItemCollectionType.Playlist)
|
if (collectionKey.CollectionType is CollectionType.RerunFirstRun or CollectionType.RerunRerun)
|
||||||
|
{
|
||||||
|
await _rerunHelper.InitWithMediaItems(playout.Id, collectionKey, mediaItems, cancellationToken);
|
||||||
|
return _rerunHelper.CreateEnumerator(collectionKey, state, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collectionKey.CollectionType is CollectionType.Playlist)
|
||||||
{
|
{
|
||||||
foreach (int playlistId in Optional(collectionKey.PlaylistId))
|
foreach (int playlistId in Optional(collectionKey.PlaylistId))
|
||||||
{
|
{
|
||||||
@@ -1243,7 +1272,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
|
|
||||||
int collectionId = collectionKey.CollectionId ?? 0;
|
int collectionId = collectionKey.CollectionId ?? 0;
|
||||||
|
|
||||||
if (collectionKey.CollectionType == ProgramScheduleItemCollectionType.Collection &&
|
if (collectionKey.CollectionType == CollectionType.Collection &&
|
||||||
await _mediaCollectionRepository.IsCustomPlaybackOrder(collectionId))
|
await _mediaCollectionRepository.IsCustomPlaybackOrder(collectionId))
|
||||||
{
|
{
|
||||||
Option<Collection> maybeCollectionWithItems =
|
Option<Collection> maybeCollectionWithItems =
|
||||||
@@ -1297,7 +1326,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
|||||||
activeSchedule.RandomStartPoint,
|
activeSchedule.RandomStartPoint,
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
case PlaybackOrder.MultiEpisodeShuffle when
|
case PlaybackOrder.MultiEpisodeShuffle when
|
||||||
collectionKey.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow &&
|
collectionKey.CollectionType == CollectionType.TelevisionShow &&
|
||||||
collectionKey.MediaItemId.HasValue:
|
collectionKey.MediaItemId.HasValue:
|
||||||
foreach (Show show in await _televisionRepository.GetShow(collectionKey.MediaItemId.Value, cancellationToken))
|
foreach (Show show in await _televisionRepository.GetShow(collectionKey.MediaItemId.Value, cancellationToken))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
CurrentTime = nextState.CurrentTime + itemDuration
|
CurrentTime = nextState.CurrentTime + itemDuration
|
||||||
};
|
};
|
||||||
|
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
CurrentTime = nextItemStart.UtcDateTime
|
CurrentTime = nextItemStart.UtcDateTime
|
||||||
};
|
};
|
||||||
|
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,9 +365,9 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert playlist filler
|
// convert playlist filler
|
||||||
if (allFiller.Any(f => f.CollectionType is ProgramScheduleItemCollectionType.Playlist))
|
if (allFiller.Any(f => f.CollectionType is CollectionType.Playlist))
|
||||||
{
|
{
|
||||||
var toRemove = allFiller.Filter(f => f.CollectionType is ProgramScheduleItemCollectionType.Playlist)
|
var toRemove = allFiller.Filter(f => f.CollectionType is CollectionType.Playlist)
|
||||||
.ToList();
|
.ToList();
|
||||||
allFiller.RemoveAll(toRemove.Contains);
|
allFiller.RemoveAll(toRemove.Contains);
|
||||||
|
|
||||||
@@ -800,7 +800,9 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
};
|
};
|
||||||
|
|
||||||
result.Add(playoutItem);
|
result.Add(playoutItem);
|
||||||
enumerator.MoveNext();
|
|
||||||
|
// TODO: this won't work with reruns
|
||||||
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,7 +847,9 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
|
|
||||||
remainingToFill -= itemDuration;
|
remainingToFill -= itemDuration;
|
||||||
result.Add(playoutItem);
|
result.Add(playoutItem);
|
||||||
enumerator.MoveNext();
|
|
||||||
|
// TODO: this won't work with reruns
|
||||||
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -857,7 +861,8 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
remainingToFill);
|
remainingToFill);
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerator.MoveNext();
|
// TODO: this won't work with reruns
|
||||||
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,7 +897,8 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
|||||||
DisableWatermarks = !scheduleItem.FallbackFiller.AllowWatermarks
|
DisableWatermarks = !scheduleItem.FallbackFiller.AllowWatermarks
|
||||||
};
|
};
|
||||||
|
|
||||||
enumerator.MoveNext();
|
// TODO: this won't work with reruns
|
||||||
|
enumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
|
|||||||
itemDuration,
|
itemDuration,
|
||||||
scheduleItem.PlayoutDuration);
|
scheduleItem.PlayoutDuration);
|
||||||
|
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
|
|||||||
itemDuration,
|
itemDuration,
|
||||||
remainingDuration);
|
remainingDuration);
|
||||||
|
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -235,7 +235,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
|
|||||||
: nextState.NextGuideGroup
|
: nextState.NextGuideGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(itemStartTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul
|
|||||||
: nextState.NextGuideGroup
|
: nextState.NextGuideGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(itemStartTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
|
|||||||
: nextState.NextGuideGroup
|
: nextState.NextGuideGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(playoutItem.StartOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextState.MultipleRemaining.IfNone(-1) == 0)
|
if (nextState.MultipleRemaining.IfNone(-1) == 0)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI
|
|||||||
};
|
};
|
||||||
|
|
||||||
nextState.ScheduleItemsEnumerator.MoveNext();
|
nextState.ScheduleItemsEnumerator.MoveNext();
|
||||||
contentEnumerator.MoveNext();
|
contentEnumerator.MoveNext(itemStartTime);
|
||||||
|
|
||||||
// LogScheduledItem(scheduleItem, mediaItem, itemStartTime);
|
// LogScheduledItem(scheduleItem, mediaItem, itemStartTime);
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ public class RandomizedMediaCollectionEnumerator : IMediaCollectionEnumerator
|
|||||||
// because _index defaults to 0
|
// because _index defaults to 0
|
||||||
if (State.Index == state.Index)
|
if (State.Index == state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (State.Index <= state.Index)
|
while (State.Index <= state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ public class RandomizedMediaCollectionEnumerator : IMediaCollectionEnumerator
|
|||||||
public Option<MediaItem> Current => _mediaItems.Any() ? _mediaItems[_index] : None;
|
public Option<MediaItem> Current => _mediaItems.Any() ? _mediaItems[_index] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext()
|
public void MoveNext(Option<DateTimeOffset> scheduledAt)
|
||||||
{
|
{
|
||||||
if (_mediaItems.Count == 0)
|
if (_mediaItems.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ public class RandomizedRotatingMediaCollectionEnumerator : IMediaCollectionEnume
|
|||||||
// because _index defaults to 0
|
// because _index defaults to 0
|
||||||
if (State.Index == state.Index)
|
if (State.Index == state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (State.Index <= state.Index)
|
while (State.Index <= state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ public class RandomizedRotatingMediaCollectionEnumerator : IMediaCollectionEnume
|
|||||||
public Option<MediaItem> Current => _mediaItems.Any() ? _mediaItems[_index] : None;
|
public Option<MediaItem> Current => _mediaItems.Any() ? _mediaItems[_index] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext()
|
public void MoveNext(Option<DateTimeOffset> scheduledAt)
|
||||||
{
|
{
|
||||||
var groups = _groupMedia.Keys.ToList();
|
var groups = _groupMedia.Keys.ToList();
|
||||||
if (groups.Count == 0)
|
if (groups.Count == 0)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public sealed class SeasonEpisodeMediaCollectionEnumerator : IMediaCollectionEnu
|
|||||||
|
|
||||||
while (State.Index < state.Index)
|
while (State.Index < state.Index)
|
||||||
{
|
{
|
||||||
MoveNext();
|
MoveNext(Option<DateTimeOffset>.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ public sealed class SeasonEpisodeMediaCollectionEnumerator : IMediaCollectionEnu
|
|||||||
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
public Option<MediaItem> Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None;
|
||||||
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
public Option<bool> CurrentIncludeInProgramGuide { get; }
|
||||||
|
|
||||||
public void MoveNext()
|
public void MoveNext(Option<DateTimeOffset> scheduledAt)
|
||||||
{
|
{
|
||||||
if (_sortedMediaItems.Count == 0)
|
if (_sortedMediaItems.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user