diff --git a/CHANGELOG.md b/CHANGELOG.md index a079a5640..dff000f87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - AviSynth itself needs to be installed - Add `Troubleshoot` button to classic schedule list - This generates JSON representing the entire schedule which can be shared when requested for troubleshooting +- Add **Settings** > **FFmpeg** > **Probe For Interlaced Frames** + - When enabled, this will probe *local content* for interlaced frames on demand (immediately before playback) + - This will be used as a more accurate check for interlaced content + - The result will be cached (only probed once and stored) in the database along with all other media item statistics (e.g. duration) + - This feature will currently ignore content that is not streamed from disk ### Fixed - Fix HLS Direct playback with Jellyfin 10.11 diff --git a/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs b/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs index e49eac0bc..e8670e078 100644 --- a/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs +++ b/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs @@ -113,6 +113,11 @@ public class UpdateFFmpegSettingsHandler( await workerChannel.WriteAsync(new ExtractEmbeddedSubtitles(Option.None), cancellationToken); } + await configElementRepository.Upsert( + ConfigElementKey.FFmpegProbeForInterlacedFrames, + request.Settings.ProbeForInterlacedFrames, + cancellationToken); + if (request.Settings.GlobalWatermarkId is not null) { await configElementRepository.Upsert( diff --git a/ErsatzTV.Application/FFmpegProfiles/FFmpegSettingsViewModel.cs b/ErsatzTV.Application/FFmpegProfiles/FFmpegSettingsViewModel.cs index 8bd47b749..e411bd9dd 100644 --- a/ErsatzTV.Application/FFmpegProfiles/FFmpegSettingsViewModel.cs +++ b/ErsatzTV.Application/FFmpegProfiles/FFmpegSettingsViewModel.cs @@ -10,6 +10,7 @@ public class FFmpegSettingsViewModel public string PreferredAudioLanguageCode { get; set; } public bool UseEmbeddedSubtitles { get; set; } public bool ExtractEmbeddedSubtitles { get; set; } + public bool ProbeForInterlacedFrames { get; set; } public bool SaveReports { get; set; } public int? GlobalWatermarkId { get; set; } public int? GlobalFallbackFillerId { get; set; } diff --git a/ErsatzTV.Application/FFmpegProfiles/Queries/GetFFmpegSettingsHandler.cs b/ErsatzTV.Application/FFmpegProfiles/Queries/GetFFmpegSettingsHandler.cs index d75ba0ff2..dd3a80d6d 100644 --- a/ErsatzTV.Application/FFmpegProfiles/Queries/GetFFmpegSettingsHandler.cs +++ b/ErsatzTV.Application/FFmpegProfiles/Queries/GetFFmpegSettingsHandler.cs @@ -33,6 +33,10 @@ public class GetFFmpegSettingsHandler(IConfigElementRepository configElementRepo await configElementRepository.GetValue( ConfigElementKey.FFmpegExtractEmbeddedSubtitles, cancellationToken); + Option probeForInterlacedFrames = + await configElementRepository.GetValue( + ConfigElementKey.FFmpegProbeForInterlacedFrames, + cancellationToken); Option watermark = await configElementRepository.GetValue(ConfigElementKey.FFmpegGlobalWatermarkId, cancellationToken); Option fallbackFiller = @@ -62,6 +66,7 @@ public class GetFFmpegSettingsHandler(IConfigElementRepository configElementRepo SaveReports = await saveReports.IfNoneAsync(false), UseEmbeddedSubtitles = await useEmbeddedSubtitles.IfNoneAsync(true), ExtractEmbeddedSubtitles = await extractEmbeddedSubtitles.IfNoneAsync(false), + ProbeForInterlacedFrames = await probeForInterlacedFrames.IfNoneAsync(false), PreferredAudioLanguageCode = await preferredAudioLanguageCode.IfNoneAsync("eng"), HlsSegmenterIdleTimeout = await hlsSegmenterIdleTimeout.IfNoneAsync(60), WorkAheadSegmenterLimit = await workAheadSegmenterLimit.IfNoneAsync(1), diff --git a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs index 5c65b9dae..c463de009 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs @@ -408,7 +408,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< ffprobePath, saveReports, channel, - videoVersion, + new MediaItemVideoVersion(playoutItemWithPath.PlayoutItem.MediaItem, videoVersion), new MediaItemAudioVersion(playoutItemWithPath.PlayoutItem.MediaItem, audioVersion), videoPath, audioPath, diff --git a/ErsatzTV.Application/Troubleshooting/Commands/PrepareTroubleshootingPlaybackHandler.cs b/ErsatzTV.Application/Troubleshooting/Commands/PrepareTroubleshootingPlaybackHandler.cs index 71543c90f..4ec0cd4c0 100644 --- a/ErsatzTV.Application/Troubleshooting/Commands/PrepareTroubleshootingPlaybackHandler.cs +++ b/ErsatzTV.Application/Troubleshooting/Commands/PrepareTroubleshootingPlaybackHandler.cs @@ -224,7 +224,7 @@ public class PrepareTroubleshootingPlaybackHandler( ffprobePath, true, channel, - videoVersion, + new MediaItemVideoVersion(mediaItem, videoVersion), new MediaItemAudioVersion(mediaItem, version), videoPath, mediaPath, diff --git a/ErsatzTV.Core/Domain/ConfigElementKey.cs b/ErsatzTV.Core/Domain/ConfigElementKey.cs index 5ea2c5265..7f4661321 100644 --- a/ErsatzTV.Core/Domain/ConfigElementKey.cs +++ b/ErsatzTV.Core/Domain/ConfigElementKey.cs @@ -19,6 +19,7 @@ public class ConfigElementKey public static ConfigElementKey FFmpegSaveReports => new("ffmpeg.save_reports"); public static ConfigElementKey FFmpegUseEmbeddedSubtitles => new("ffmpeg.use_embedded_subtitles"); public static ConfigElementKey FFmpegExtractEmbeddedSubtitles => new("ffmpeg.extract_embedded_subtitles"); + public static ConfigElementKey FFmpegProbeForInterlacedFrames => new("ffmpeg.probe_for_interlaced_frames"); public static ConfigElementKey FFmpegPreferredLanguageCode => new("ffmpeg.preferred_language_code"); public static ConfigElementKey FFmpegGlobalWatermarkId => new("ffmpeg.global_watermark_id"); public static ConfigElementKey FFmpegGlobalFallbackFillerId => new("ffmpeg.global_fallback_filler_id"); diff --git a/ErsatzTV.Core/Domain/MediaItem/MediaVersion.cs b/ErsatzTV.Core/Domain/MediaItem/MediaVersion.cs index c4091ad24..ae8485138 100644 --- a/ErsatzTV.Core/Domain/MediaItem/MediaVersion.cs +++ b/ErsatzTV.Core/Domain/MediaItem/MediaVersion.cs @@ -14,6 +14,7 @@ public class MediaVersion : IDisplaySize public string DisplayAspectRatio { get; set; } public string RFrameRate { get; set; } public VideoScanKind VideoScanKind { get; set; } + public double? InterlacedRatio { get; set; } public DateTime DateAdded { get; set; } public DateTime DateUpdated { get; set; } public int Width { get; set; } diff --git a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs index b64e10f3a..cda60f977 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs @@ -4,7 +4,9 @@ using CliWrap; using CliWrap.Buffered; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; +using ErsatzTV.Core.Extensions; using ErsatzTV.Core.Interfaces.FFmpeg; +using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Interfaces.Streaming; using ErsatzTV.FFmpeg; @@ -26,6 +28,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService private readonly IGraphicsElementLoader _graphicsElementLoader; private readonly IMemoryCache _memoryCache; private readonly IMpegTsScriptService _mpegTsScriptService; + private readonly ILocalStatisticsProvider _localStatisticsProvider; + private readonly IMediaItemRepository _mediaItemRepository; private readonly ICustomStreamSelector _customStreamSelector; private readonly FFmpegProcessService _ffmpegProcessService; private readonly IFFmpegStreamSelector _ffmpegStreamSelector; @@ -43,6 +47,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService IGraphicsElementLoader graphicsElementLoader, IMemoryCache memoryCache, IMpegTsScriptService mpegTsScriptService, + ILocalStatisticsProvider localStatisticsProvider, + IMediaItemRepository mediaItemRepository, ILogger logger) { _ffmpegProcessService = ffmpegProcessService; @@ -54,6 +60,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService _graphicsElementLoader = graphicsElementLoader; _memoryCache = memoryCache; _mpegTsScriptService = mpegTsScriptService; + _localStatisticsProvider = localStatisticsProvider; + _mediaItemRepository = mediaItemRepository; _logger = logger; } @@ -62,7 +70,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService string ffprobePath, bool saveReports, Channel channel, - MediaVersion videoVersion, + MediaItemVideoVersion videoVersion, MediaItemAudioVersion audioVersion, string videoPath, string audioPath, @@ -92,7 +100,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService bool canProxy, CancellationToken cancellationToken) { - MediaStream videoStream = await _ffmpegStreamSelector.SelectVideoStream(videoVersion); + MediaStream videoStream = await _ffmpegStreamSelector.SelectVideoStream(videoVersion.MediaVersion); // we cannot burst live input hlsRealtime = hlsRealtime || streamInputKind is StreamInputKind.Live; @@ -100,7 +108,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettingsCalculator.CalculateSettings( channel.StreamingMode, channel.FFmpegProfile, - videoVersion, + videoVersion.MediaVersion, videoStream, start, now, @@ -214,6 +222,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService }; }); + ScanKind scanKind = await ProbeScanKind(ffmpegPath, videoVersion.MediaItem, cancellationToken); + var ffmpegVideoStream = new VideoStream( videoStream.Index, videoStream.Codec, @@ -224,12 +234,12 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService videoStream.ColorSpace, videoStream.ColorTransfer, videoStream.ColorPrimaries), - new FrameSize(videoVersion.Width, videoVersion.Height), - videoVersion.SampleAspectRatio, - videoVersion.DisplayAspectRatio, - videoVersion.RFrameRate, + new FrameSize(videoVersion.MediaVersion.Width, videoVersion.MediaVersion.Height), + videoVersion.MediaVersion.SampleAspectRatio, + videoVersion.MediaVersion.DisplayAspectRatio, + videoVersion.MediaVersion.RFrameRate, videoPath != audioPath, // still image when paths are different - videoVersion.VideoScanKind == VideoScanKind.Progressive ? ScanKind.Progressive : ScanKind.Interlaced); + scanKind); var videoInputFile = new VideoInputFile( videoPath, @@ -455,8 +465,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService if (channel.FFmpegProfile.ScalingBehavior is ScalingBehavior.Crop) { - bool isTooSmallToCrop = videoVersion.Height < channel.FFmpegProfile.Resolution.Height || - videoVersion.Width < channel.FFmpegProfile.Resolution.Width; + bool isTooSmallToCrop = videoVersion.MediaVersion.Height < channel.FFmpegProfile.Resolution.Height || + videoVersion.MediaVersion.Width < channel.FFmpegProfile.Resolution.Width; // if any dimension is smaller than the crop, scale beyond the crop (beyond the target resolution) if (isTooSmallToCrop) @@ -546,7 +556,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService ptsOffset, playbackSettings.ThreadCount, qsvExtraHardwareFrames, - videoVersion is BackgroundImageMediaVersion { IsSongWithProgress: true }, + videoVersion.MediaVersion is BackgroundImageMediaVersion { IsSongWithProgress: true }, false, GetTonemapAlgorithm(playbackSettings), channel.UniqueId == Guid.Empty); @@ -584,6 +594,47 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService return new PlayoutItemResult(command, graphicsEngineContext); } + private async Task ProbeScanKind( + string ffmpegPath, + MediaItem mediaItem, + CancellationToken cancellationToken) + { + var headVersion = mediaItem.GetHeadVersion(); + if (headVersion.VideoScanKind is VideoScanKind.Interlaced) + { + _logger.LogDebug("Container is marked {ScanKind}", headVersion.VideoScanKind); + return ScanKind.Interlaced; + } + + // skip probe if disabled + if (!await _configElementRepository.GetValue( + ConfigElementKey.FFmpegProbeForInterlacedFrames, + cancellationToken).IfNoneAsync(false)) + { + _logger.LogDebug("Probe for interlaced frames is disabled"); + return ScanKind.Progressive; + } + + if (headVersion.InterlacedRatio is null) + { + _logger.LogDebug("Will probe for interlaced frames"); + + Option maybeInterlacedRatio = + await _localStatisticsProvider.GetInterlacedRatio(ffmpegPath, mediaItem, cancellationToken); + foreach (double ratio in maybeInterlacedRatio) + { + await _mediaItemRepository.SetInterlacedRatio(mediaItem, ratio); + } + } + + var result = headVersion.InterlacedRatio > 0.05 ? ScanKind.Interlaced : ScanKind.Progressive; + _logger.LogDebug( + "Content has interlaced ratio of {Ratio} - will consider as {ScanKind}", + headVersion.InterlacedRatio, + result); + return result; + } + public async Task ForError( string ffmpegPath, Channel channel, @@ -847,7 +898,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService // TODO: save reports? string defaultScript = await _configElementRepository .GetValue(ConfigElementKey.FFmpegDefaultMpegTsScript, cancellationToken) - .IfNoneAsync("default"); + .IfNoneAsync("Default"); List allScripts = _mpegTsScriptService.GetScripts(); Option maybeScript = Optional(allScripts.Find(s => s.Id == defaultScript)); foreach (var script in maybeScript) diff --git a/ErsatzTV.Core/FFmpeg/MediaItemVideoVersion.cs b/ErsatzTV.Core/FFmpeg/MediaItemVideoVersion.cs new file mode 100644 index 000000000..3a8746862 --- /dev/null +++ b/ErsatzTV.Core/FFmpeg/MediaItemVideoVersion.cs @@ -0,0 +1,5 @@ +using ErsatzTV.Core.Domain; + +namespace ErsatzTV.Core.FFmpeg; + +public record MediaItemVideoVersion(MediaItem MediaItem, MediaVersion MediaVersion); diff --git a/ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs b/ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs index 096b827dc..499431436 100644 --- a/ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs +++ b/ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs @@ -14,7 +14,7 @@ public interface IFFmpegProcessService string ffprobePath, bool saveReports, Channel channel, - MediaVersion videoVersion, + MediaItemVideoVersion videoVersion, MediaItemAudioVersion audioVersion, string videoPath, string audioPath, diff --git a/ErsatzTV.Core/Interfaces/Metadata/ILocalStatisticsProvider.cs b/ErsatzTV.Core/Interfaces/Metadata/ILocalStatisticsProvider.cs index 235e4f8e9..933b64b33 100644 --- a/ErsatzTV.Core/Interfaces/Metadata/ILocalStatisticsProvider.cs +++ b/ErsatzTV.Core/Interfaces/Metadata/ILocalStatisticsProvider.cs @@ -9,4 +9,9 @@ public interface ILocalStatisticsProvider Task> RefreshStatistics(string ffmpegPath, string ffprobePath, MediaItem mediaItem); Either> GetSongTags(MediaItem mediaItem); + + Task> GetInterlacedRatio( + string ffmpegPath, + MediaItem mediaItem, + CancellationToken cancellationToken); } diff --git a/ErsatzTV.Core/Interfaces/Repositories/IMediaItemRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/IMediaItemRepository.cs index 199dc177e..387878106 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/IMediaItemRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/IMediaItemRepository.cs @@ -13,4 +13,5 @@ public interface IMediaItemRepository Task FlagNormal(MediaItem mediaItem); Task> DeleteItems(List mediaItemIds); Task> GetAllTrashedItems(LibraryPath libraryPath); + Task SetInterlacedRatio(MediaItem mediaItem, double interlacedRatio); } diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.Designer.cs b/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.Designer.cs new file mode 100644 index 000000000..21421e168 --- /dev/null +++ b/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.Designer.cs @@ -0,0 +1,6870 @@ +// +using System; +using ErsatzTV.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ErsatzTV.Infrastructure.MySql.Migrations +{ + [DbContext(typeof(TvContext))] + [Migration("20251110043500_Add_MediaVersionInterlacedRatio")] + partial class Add_MediaVersionInterlacedRatio + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("ArtworkId") + .HasColumnType("int"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("Role") + .HasColumnType("longtext"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ArtworkId") + .IsUnique(); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Actor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("Biography") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("Disambiguation") + .HasColumnType("longtext"); + + b.Property("Formed") + .HasColumnType("longtext"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistId"); + + b.ToTable("ArtistMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("ArtworkKind") + .HasColumnType("int"); + + b.Property("BlurHash43") + .HasColumnType("longtext"); + + b.Property("BlurHash54") + .HasColumnType("longtext"); + + b.Property("BlurHash64") + .HasColumnType("longtext"); + + b.Property("ChannelId") + .HasColumnType("int"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("OriginalContentType") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.Property("SourcePath") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ChannelId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Artwork", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemGraphicsElement", b => + { + b.Property("BlockItemId") + .HasColumnType("int"); + + b.Property("GraphicsElementId") + .HasColumnType("int"); + + b.HasKey("BlockItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("BlockItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemWatermark", b => + { + b.Property("BlockItemId") + .HasColumnType("int"); + + b.Property("WatermarkId") + .HasColumnType("int"); + + b.HasKey("BlockItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("BlockItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Categories") + .HasColumnType("longtext"); + + b.Property("FFmpegProfileId") + .HasColumnType("int"); + + b.Property("FallbackFillerId") + .HasColumnType("int"); + + b.Property("Group") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("longtext") + .HasDefaultValue("ErsatzTV"); + + b.Property("IdleBehavior") + .HasColumnType("int"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("MirrorSourceChannelId") + .HasColumnType("int"); + + b.Property("MusicVideoCreditsMode") + .HasColumnType("int"); + + b.Property("MusicVideoCreditsTemplate") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Number") + .HasColumnType("varchar(255)"); + + b.Property("PlayoutMode") + .HasColumnType("int"); + + b.Property("PlayoutOffset") + .HasColumnType("time(6)"); + + b.Property("PlayoutSource") + .HasColumnType("int"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("longtext"); + + b.Property("PreferredAudioTitle") + .HasColumnType("longtext"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("longtext"); + + b.Property("ShowInEpg") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("SongVideoMode") + .HasColumnType("int"); + + b.Property("SortNumber") + .HasColumnType("double"); + + b.Property("StreamSelector") + .HasColumnType("longtext"); + + b.Property("StreamSelectorMode") + .HasColumnType("int"); + + b.Property("StreamingMode") + .HasColumnType("int"); + + b.Property("SubtitleMode") + .HasColumnType("int"); + + b.Property("TranscodeMode") + .HasColumnType("int"); + + b.Property("UniqueId") + .HasColumnType("char(36)"); + + b.Property("WatermarkId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FFmpegProfileId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("MirrorSourceChannelId"); + + b.HasIndex("Number") + .IsUnique(); + + b.HasIndex("WatermarkId"); + + b.ToTable("Channel", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ChannelWatermark", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DurationSeconds") + .HasColumnType("int"); + + b.Property("FrequencyMinutes") + .HasColumnType("int"); + + b.Property("HorizontalMarginPercent") + .HasColumnType("double"); + + b.Property("Image") + .HasColumnType("longtext"); + + b.Property("ImageSource") + .HasColumnType("int"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Opacity") + .HasColumnType("int"); + + b.Property("OpacityExpression") + .HasColumnType("longtext"); + + b.Property("OriginalContentType") + .HasColumnType("longtext"); + + b.Property("PlaceWithinSourceContent") + .HasColumnType("tinyint(1)"); + + b.Property("Size") + .HasColumnType("int"); + + b.Property("VerticalMarginPercent") + .HasColumnType("double"); + + b.Property("WidthPercent") + .HasColumnType("double"); + + b.Property("ZIndex") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ChannelWatermark", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("UseCustomPlaybackOrder") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("CustomIndex") + .HasColumnType("int"); + + b.HasKey("CollectionId", "MediaItemId"); + + b.HasIndex("MediaItemId"); + + b.ToTable("CollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ConfigElement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Key") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("ConfigElement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoGraphicsElement", b => + { + b.Property("DecoId") + .HasColumnType("int"); + + b.Property("GraphicsElementId") + .HasColumnType("int"); + + b.HasKey("DecoId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("DecoGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoWatermark", b => + { + b.Property("DecoId") + .HasColumnType("int"); + + b.Property("WatermarkId") + .HasColumnType("int"); + + b.HasKey("DecoId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("DecoWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.ToTable("Director", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("EmbyMediaSourceId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EmbyMediaSourceId") + .HasColumnType("int"); + + b.Property("EmbyPath") + .HasColumnType("longtext"); + + b.Property("LocalPath") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeId") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("Outline") + .HasColumnType("longtext"); + + b.Property("Plot") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Tagline") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.ToTable("EpisodeMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AllowBFrames") + .HasColumnType("tinyint(1)"); + + b.Property("AudioBitrate") + .HasColumnType("int"); + + b.Property("AudioBufferSize") + .HasColumnType("int"); + + b.Property("AudioChannels") + .HasColumnType("int"); + + b.Property("AudioFormat") + .HasColumnType("int"); + + b.Property("AudioSampleRate") + .HasColumnType("int"); + + b.Property("BitDepth") + .HasColumnType("int"); + + b.Property("DeinterlaceVideo") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("HardwareAcceleration") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("NormalizeFramerate") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("NormalizeLoudnessMode") + .HasColumnType("int"); + + b.Property("QsvExtraHardwareFrames") + .HasColumnType("int"); + + b.Property("ResolutionId") + .HasColumnType("int"); + + b.Property("ScalingBehavior") + .HasColumnType("int"); + + b.Property("ThreadCount") + .HasColumnType("int"); + + b.Property("TonemapAlgorithm") + .HasColumnType("int"); + + b.Property("VaapiDevice") + .HasColumnType("longtext"); + + b.Property("VaapiDisplay") + .HasColumnType("longtext"); + + b.Property("VaapiDriver") + .HasColumnType("int"); + + b.Property("VideoBitrate") + .HasColumnType("int"); + + b.Property("VideoBufferSize") + .HasColumnType("int"); + + b.Property("VideoFormat") + .HasColumnType("int"); + + b.Property("VideoPreset") + .HasColumnType("longtext"); + + b.Property("VideoProfile") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ResolutionId"); + + b.ToTable("FFmpegProfile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AllowWatermarks") + .HasColumnType("tinyint(1)"); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("Duration") + .HasColumnType("time(6)"); + + b.Property("Expression") + .HasColumnType("longtext"); + + b.Property("FillerKind") + .HasColumnType("int"); + + b.Property("FillerMode") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("PadToNearestMinute") + .HasColumnType("int"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.Property("UseChaptersAsMediaItems") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("FillerPreset", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Genre"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.GraphicsElement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("GraphicsElement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageFolderDuration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DurationSeconds") + .HasColumnType("double"); + + b.Property("LibraryFolderId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LibraryFolderId") + .IsUnique(); + + b.ToTable("ImageFolderDuration", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("DurationSeconds") + .HasColumnType("double"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.ToTable("ImageMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("int"); + + b.Property("JellyfinPath") + .HasColumnType("longtext"); + + b.Property("LocalPath") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LanguageCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EnglishName") + .HasColumnType("longtext"); + + b.Property("FrenchName") + .HasColumnType("longtext"); + + b.Property("ThreeCode1") + .HasColumnType("longtext"); + + b.Property("ThreeCode2") + .HasColumnType("longtext"); + + b.Property("TwoCode") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("LanguageCode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LastScan") + .HasColumnType("datetime(6)"); + + b.Property("MediaKind") + .HasColumnType("int"); + + b.Property("MediaSourceId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MediaSourceId"); + + b.ToTable("Library", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("LibraryPathId") + .HasColumnType("int"); + + b.Property("ParentId") + .HasColumnType("int"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.HasIndex("ParentId"); + + b.ToTable("LibraryFolder", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LastScan") + .HasColumnType("datetime(6)"); + + b.Property("LibraryId") + .HasColumnType("int"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryPath", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ChapterId") + .HasColumnType("bigint"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("MediaVersionId") + .HasColumnType("int"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaChapter", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LibraryFolderId") + .HasColumnType("int"); + + b.Property("MediaVersionId") + .HasColumnType("int"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.Property("PathHash") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("LibraryFolderId"); + + b.HasIndex("MediaVersionId"); + + b.HasIndex("PathHash") + .IsUnique(); + + b.ToTable("MediaFile", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LibraryPathId") + .HasColumnType("int"); + + b.Property("State") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.ToTable("MediaItem", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.HasKey("Id"); + + b.ToTable("MediaSource", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AttachedPic") + .HasColumnType("tinyint(1)"); + + b.Property("BitsPerRawSample") + .HasColumnType("int"); + + b.Property("Channels") + .HasColumnType("int"); + + b.Property("Codec") + .HasColumnType("longtext"); + + b.Property("ColorPrimaries") + .HasColumnType("longtext"); + + b.Property("ColorRange") + .HasColumnType("longtext"); + + b.Property("ColorSpace") + .HasColumnType("longtext"); + + b.Property("ColorTransfer") + .HasColumnType("longtext"); + + b.Property("Default") + .HasColumnType("tinyint(1)"); + + b.Property("FileName") + .HasColumnType("longtext"); + + b.Property("Forced") + .HasColumnType("tinyint(1)"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("MediaStreamKind") + .HasColumnType("int"); + + b.Property("MediaVersionId") + .HasColumnType("int"); + + b.Property("MimeType") + .HasColumnType("longtext"); + + b.Property("PixelFormat") + .HasColumnType("longtext"); + + b.Property("Profile") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaStream", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("DisplayAspectRatio") + .HasColumnType("longtext"); + + b.Property("Duration") + .HasColumnType("time(6)"); + + b.Property("EpisodeId") + .HasColumnType("int"); + + b.Property("Height") + .HasColumnType("int"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("InterlacedRatio") + .HasColumnType("double"); + + b.Property("MovieId") + .HasColumnType("int"); + + b.Property("MusicVideoId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoId") + .HasColumnType("int"); + + b.Property("RFrameRate") + .HasColumnType("longtext"); + + b.Property("RemoteStreamId") + .HasColumnType("int"); + + b.Property("SampleAspectRatio") + .HasColumnType("longtext"); + + b.Property("SongId") + .HasColumnType("int"); + + b.Property("VideoScanKind") + .HasColumnType("int"); + + b.Property("Width") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.HasIndex("ImageId"); + + b.HasIndex("MovieId"); + + b.HasIndex("MusicVideoId"); + + b.HasIndex("OtherVideoId"); + + b.HasIndex("RemoteStreamId"); + + b.HasIndex("SongId"); + + b.ToTable("MediaVersion", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("Guid") + .HasColumnType("longtext"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("MetadataGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Mood"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ContentRating") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("MovieId") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("Outline") + .HasColumnType("longtext"); + + b.Property("Plot") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Tagline") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MovieId"); + + b.ToTable("MovieMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("MultiCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("ScheduleAsGroup") + .HasColumnType("tinyint(1)"); + + b.HasKey("MultiCollectionId", "CollectionId"); + + b.HasIndex("CollectionId"); + + b.ToTable("MultiCollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("ScheduleAsGroup") + .HasColumnType("tinyint(1)"); + + b.HasKey("MultiCollectionId", "SmartCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("MultiCollectionSmartItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoArtist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MusicVideoMetadataId"); + + b.ToTable("MusicVideoArtist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Album") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("MusicVideoId") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("Plot") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Track") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MusicVideoId"); + + b.ToTable("MusicVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ContentRating") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("OtherVideoId") + .HasColumnType("int"); + + b.Property("Outline") + .HasColumnType("longtext"); + + b.Property("Plot") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Tagline") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("OtherVideoId"); + + b.ToTable("OtherVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("PlaylistGroupId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlaylistGroupId", "Name") + .IsUnique(); + + b.ToTable("Playlist", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PlaylistGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("IncludeInProgramGuide") + .HasColumnType("tinyint(1)"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("PlayAll") + .HasColumnType("tinyint(1)"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("PlaylistItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("int"); + + b.Property("DailyRebuildTime") + .HasColumnType("time(6)"); + + b.Property("DecoId") + .HasColumnType("int"); + + b.Property("OnDemandCheckpoint") + .HasColumnType("datetime(6)"); + + b.Property("ProgramScheduleId") + .HasColumnType("int"); + + b.Property("ScheduleFile") + .HasColumnType("longtext"); + + b.Property("ScheduleKind") + .HasColumnType("int"); + + b.Property("Seed") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("DecoId"); + + b.HasIndex("ProgramScheduleId"); + + b.ToTable("Playout", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutBuildStatus", b => + { + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("LastBuild") + .HasColumnType("datetime(6)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("Success") + .HasColumnType("tinyint(1)"); + + b.HasKey("PlayoutId"); + + b.ToTable("PlayoutBuildStatus", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutGap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Finish") + .HasColumnType("datetime(6)"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("Start") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("Start", "Finish") + .HasDatabaseName("IX_PlayoutGap_Start_Finish"); + + b.ToTable("PlayoutGap", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlockKey") + .HasColumnType("longtext"); + + b.Property("ChapterTitle") + .HasColumnType("longtext"); + + b.Property("CollectionEtag") + .HasColumnType("longtext"); + + b.Property("CollectionKey") + .HasColumnType("longtext"); + + b.Property("CustomTitle") + .HasColumnType("longtext"); + + b.Property("DisableWatermarks") + .HasColumnType("tinyint(1)"); + + b.Property("FillerKind") + .HasColumnType("int"); + + b.Property("Finish") + .HasColumnType("datetime(6)"); + + b.Property("GuideFinish") + .HasColumnType("datetime(6)"); + + b.Property("GuideGroup") + .HasColumnType("int"); + + b.Property("GuideStart") + .HasColumnType("datetime(6)"); + + b.Property("InPoint") + .HasColumnType("time(6)"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("OutPoint") + .HasColumnType("time(6)"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("longtext"); + + b.Property("PreferredAudioTitle") + .HasColumnType("longtext"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("longtext"); + + b.Property("Start") + .HasColumnType("datetime(6)"); + + b.Property("SubtitleMode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("Start", "Finish") + .HasDatabaseName("IX_PlayoutItem_Start_Finish"); + + b.ToTable("PlayoutItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemGraphicsElement", b => + { + b.Property("PlayoutItemId") + .HasColumnType("int"); + + b.Property("GraphicsElementId") + .HasColumnType("int"); + + b.Property("Variables") + .HasColumnType("longtext"); + + b.HasKey("PlayoutItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("PlayoutItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemWatermark", b => + { + b.Property("PlayoutItemId") + .HasColumnType("int"); + + b.Property("WatermarkId") + .HasColumnType("int"); + + b.HasKey("PlayoutItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("PlayoutItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AnchorDate") + .HasColumnType("datetime(6)"); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("FakeCollectionKey") + .HasColumnType("longtext"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("RerunCollectionId") + .HasColumnType("int"); + + b.Property("SearchQuery") + .HasColumnType("longtext"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("RerunCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("PlayoutProgramScheduleAnchor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutScheduleItemFillGroupIndex", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("ProgramScheduleItemId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("ProgramScheduleItemId"); + + b.ToTable("PlayoutScheduleItemFillGroupIndex", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PlexMediaSourceId") + .HasColumnType("int"); + + b.Property("Uri") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LocalPath") + .HasColumnType("longtext"); + + b.Property("PlexMediaSourceId") + .HasColumnType("int"); + + b.Property("PlexPath") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("FixedStartTimeBehavior") + .HasColumnType("int"); + + b.Property("KeepMultiPartEpisodesTogether") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("RandomStartPoint") + .HasColumnType("tinyint(1)"); + + b.Property("ShuffleScheduleItems") + .HasColumnType("tinyint(1)"); + + b.Property("TreatCollectionsAsShows") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("ProgramSchedule", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleAlternate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DaysOfMonth") + .HasColumnType("longtext"); + + b.Property("DaysOfWeek") + .HasColumnType("longtext"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("MonthsOfYear") + .HasColumnType("longtext"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("ProgramScheduleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("ProgramScheduleId"); + + b.ToTable("ProgramScheduleAlternate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("CustomTitle") + .HasColumnType("longtext"); + + b.Property("FakeCollectionKey") + .HasColumnType("longtext"); + + b.Property("FallbackFillerId") + .HasColumnType("int"); + + b.Property("FillWithGroupMode") + .HasColumnType("int"); + + b.Property("FixedStartTimeBehavior") + .HasColumnType("int"); + + b.Property("GuideMode") + .HasColumnType("int"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("MarathonBatchSize") + .HasColumnType("int"); + + b.Property("MarathonGroupBy") + .HasColumnType("int"); + + b.Property("MarathonShuffleGroups") + .HasColumnType("tinyint(1)"); + + b.Property("MarathonShuffleItems") + .HasColumnType("tinyint(1)"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MidRollFillerId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("PostRollFillerId") + .HasColumnType("int"); + + b.Property("PreRollFillerId") + .HasColumnType("int"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("longtext"); + + b.Property("PreferredAudioTitle") + .HasColumnType("longtext"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("longtext"); + + b.Property("ProgramScheduleId") + .HasColumnType("int"); + + b.Property("RerunCollectionId") + .HasColumnType("int"); + + b.Property("SearchQuery") + .HasColumnType("longtext"); + + b.Property("SearchTitle") + .HasColumnType("longtext"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("SubtitleMode") + .HasColumnType("int"); + + b.Property("TailFillerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MidRollFillerId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("PostRollFillerId"); + + b.HasIndex("PreRollFillerId"); + + b.HasIndex("ProgramScheduleId"); + + b.HasIndex("RerunCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.HasIndex("TailFillerId"); + + b.ToTable("ProgramScheduleItem", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemGraphicsElement", b => + { + b.Property("ProgramScheduleItemId") + .HasColumnType("int"); + + b.Property("GraphicsElementId") + .HasColumnType("int"); + + b.HasKey("ProgramScheduleItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("ProgramScheduleItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemWatermark", b => + { + b.Property("ProgramScheduleItemId") + .HasColumnType("int"); + + b.Property("WatermarkId") + .HasColumnType("int"); + + b.HasKey("ProgramScheduleItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("ProgramScheduleItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RemoteStreamId") + .HasColumnType("int"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RemoteStreamId"); + + b.ToTable("RemoteStreamMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RerunCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("FirstRunPlaybackOrder") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("RerunPlaybackOrder") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("RerunCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Resolution", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Height") + .HasColumnType("int"); + + b.Property("IsCustom") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Width") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Resolution", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlockGroupId") + .HasColumnType("int"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("Minutes") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("StopScheduling") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BlockGroupId", "Name") + .IsUnique(); + + b.ToTable("Block", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("BlockGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlockId") + .HasColumnType("int"); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("DisableWatermarks") + .HasColumnType("tinyint(1)"); + + b.Property("IncludeInProgramGuide") + .HasColumnType("tinyint(1)"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("BlockItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BreakContentMode") + .HasColumnType("int"); + + b.Property("DeadAirFallbackCollectionId") + .HasColumnType("int"); + + b.Property("DeadAirFallbackCollectionType") + .HasColumnType("int"); + + b.Property("DeadAirFallbackMediaItemId") + .HasColumnType("int"); + + b.Property("DeadAirFallbackMode") + .HasColumnType("int"); + + b.Property("DeadAirFallbackMultiCollectionId") + .HasColumnType("int"); + + b.Property("DeadAirFallbackSmartCollectionId") + .HasColumnType("int"); + + b.Property("DecoGroupId") + .HasColumnType("int"); + + b.Property("DefaultFillerCollectionId") + .HasColumnType("int"); + + b.Property("DefaultFillerCollectionType") + .HasColumnType("int"); + + b.Property("DefaultFillerMediaItemId") + .HasColumnType("int"); + + b.Property("DefaultFillerMode") + .HasColumnType("int"); + + b.Property("DefaultFillerMultiCollectionId") + .HasColumnType("int"); + + b.Property("DefaultFillerSmartCollectionId") + .HasColumnType("int"); + + b.Property("DefaultFillerTrimToFit") + .HasColumnType("tinyint(1)"); + + b.Property("GraphicsElementsMode") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("UseGraphicsElementsDuringFiller") + .HasColumnType("tinyint(1)"); + + b.Property("UseWatermarkDuringFiller") + .HasColumnType("tinyint(1)"); + + b.Property("WatermarkMode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DeadAirFallbackCollectionId"); + + b.HasIndex("DeadAirFallbackMediaItemId"); + + b.HasIndex("DeadAirFallbackMultiCollectionId"); + + b.HasIndex("DeadAirFallbackSmartCollectionId"); + + b.HasIndex("DefaultFillerCollectionId"); + + b.HasIndex("DefaultFillerMediaItemId"); + + b.HasIndex("DefaultFillerMultiCollectionId"); + + b.HasIndex("DefaultFillerSmartCollectionId"); + + b.HasIndex("DecoGroupId", "Name") + .IsUnique(); + + b.ToTable("Deco", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoBreakContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CollectionId") + .HasColumnType("int"); + + b.Property("CollectionType") + .HasColumnType("int"); + + b.Property("DecoId") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("MultiCollectionId") + .HasColumnType("int"); + + b.Property("Placement") + .HasColumnType("int"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("SmartCollectionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("DecoId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("DecoBreakContent", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("DecoGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("DecoTemplateGroupId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("DecoTemplateGroupId", "Name") + .IsUnique(); + + b.ToTable("DecoTemplate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("DecoTemplateGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DecoId") + .HasColumnType("int"); + + b.Property("DecoTemplateId") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.HasKey("Id"); + + b.HasIndex("DecoId"); + + b.HasIndex("DecoTemplateId"); + + b.ToTable("DecoTemplateItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlockId") + .HasColumnType("int"); + + b.Property("ChildKey") + .HasColumnType("longtext"); + + b.Property("Details") + .HasColumnType("longtext"); + + b.Property("Finish") + .HasColumnType("datetime(6)"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("IsCurrentChild") + .HasColumnType("tinyint(1)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("PlaybackOrder") + .HasColumnType("int"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("PlayoutId"); + + b.ToTable("PlayoutHistory", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("DaysOfMonth") + .HasColumnType("longtext"); + + b.Property("DaysOfWeek") + .HasColumnType("longtext"); + + b.Property("DecoTemplateId") + .HasColumnType("int"); + + b.Property("EndDay") + .HasColumnType("int"); + + b.Property("EndMonth") + .HasColumnType("int"); + + b.Property("Index") + .HasColumnType("int"); + + b.Property("LimitToDateRange") + .HasColumnType("tinyint(1)"); + + b.Property("MonthsOfYear") + .HasColumnType("longtext"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("StartDay") + .HasColumnType("int"); + + b.Property("StartMonth") + .HasColumnType("int"); + + b.Property("TemplateId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DecoTemplateId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("TemplateId"); + + b.ToTable("PlayoutTemplate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.RerunHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("PlayoutId") + .HasColumnType("int"); + + b.Property("RerunCollectionId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("RerunCollectionId"); + + b.ToTable("RerunHistory", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("TemplateGroupId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TemplateGroupId", "Name") + .IsUnique(); + + b.ToTable("Template", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("TemplateGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlockId") + .HasColumnType("int"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("TemplateId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("TemplateId"); + + b.ToTable("TemplateItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("Outline") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("SeasonMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ContentRating") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("Outline") + .HasColumnType("longtext"); + + b.Property("Plot") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Tagline") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ShowId"); + + b.ToTable("ShowMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Query") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("SmartCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Album") + .HasColumnType("longtext"); + + b.PrimitiveCollection("AlbumArtists") + .HasColumnType("longtext"); + + b.PrimitiveCollection("Artists") + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("MetadataKind") + .HasColumnType("int"); + + b.Property("OriginalTitle") + .HasColumnType("longtext"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("SongId") + .HasColumnType("int"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Track") + .HasColumnType("longtext"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("SongId"); + + b.ToTable("SongMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Studio", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Style"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Subtitle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("Codec") + .HasColumnType("longtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("DateUpdated") + .HasColumnType("datetime(6)"); + + b.Property("Default") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("Forced") + .HasColumnType("tinyint(1)"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("IsExtracted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SDH") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.Property("StreamIndex") + .HasColumnType("int"); + + b.Property("SubtitleKind") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Subtitle", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ArtistMetadataId") + .HasColumnType("int"); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("ExternalCollectionId") + .HasColumnType("longtext"); + + b.Property("ExternalTypeId") + .HasColumnType("longtext"); + + b.Property("ImageMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("int"); + + b.Property("SeasonMetadataId") + .HasColumnType("int"); + + b.Property("ShowMetadataId") + .HasColumnType("int"); + + b.Property("SongMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Tag"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AutoRefresh") + .HasColumnType("tinyint(1)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("GeneratePlaylist") + .HasColumnType("tinyint(1)"); + + b.Property("ItemCount") + .HasColumnType("int"); + + b.Property("LastMatch") + .HasColumnType("datetime(6)"); + + b.Property("LastUpdate") + .HasColumnType("datetime(6)"); + + b.Property("List") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("PlaylistId") + .HasColumnType("int"); + + b.Property("TraktId") + .HasColumnType("int"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("PlaylistId"); + + b.ToTable("TraktList", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Episode") + .HasColumnType("int"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("MediaItemId") + .HasColumnType("int"); + + b.Property("Rank") + .HasColumnType("int"); + + b.Property("Season") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TraktId") + .HasColumnType("int"); + + b.Property("TraktListId") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("TraktListId"); + + b.ToTable("TraktListItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Guid") + .HasColumnType("longtext"); + + b.Property("TraktListItemId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TraktListItemId"); + + b.ToTable("TraktListItemGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EpisodeMetadataId") + .HasColumnType("int"); + + b.Property("MovieMetadataId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.ToTable("Writer", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Emby.EmbyPathInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EmbyLibraryId") + .HasColumnType("int"); + + b.Property("NetworkPath") + .HasColumnType("longtext"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("EmbyLibraryId"); + + b.ToTable("EmbyPathInfo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Jellyfin.JellyfinPathInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("JellyfinLibraryId") + .HasColumnType("int"); + + b.Property("NetworkPath") + .HasColumnType("longtext"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinLibraryId"); + + b.ToTable("JellyfinPathInfo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.Property("ShouldSyncItems") + .HasColumnType("tinyint(1)"); + + b.ToTable("EmbyLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.Property("ShouldSyncItems") + .HasColumnType("tinyint(1)"); + + b.ToTable("JellyfinLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.ToTable("LocalLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("LastNetworksScan") + .HasColumnType("datetime(6)"); + + b.Property("ShouldSyncItems") + .HasColumnType("tinyint(1)"); + + b.ToTable("PlexLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaFile"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("PlexId") + .HasColumnType("int"); + + b.ToTable("PlexMediaFile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Artist", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.HasIndex("SeasonId"); + + b.ToTable("Episode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Image", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Movie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.HasIndex("ArtistId"); + + b.ToTable("MusicVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("OtherVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("Duration") + .HasColumnType("time(6)"); + + b.Property("FallbackQuery") + .HasColumnType("longtext"); + + b.Property("IsLive") + .HasColumnType("tinyint(1)"); + + b.Property("Script") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.ToTable("RemoteStream", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("ShowId") + .HasColumnType("int"); + + b.HasIndex("ShowId"); + + b.ToTable("Season", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Show", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Song", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("LastCollectionsScan") + .HasColumnType("datetime(6)"); + + b.Property("OperatingSystem") + .HasColumnType("longtext"); + + b.Property("ServerName") + .HasColumnType("longtext"); + + b.ToTable("EmbyMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("LastCollectionsScan") + .HasColumnType("datetime(6)"); + + b.Property("OperatingSystem") + .HasColumnType("longtext"); + + b.Property("ServerName") + .HasColumnType("longtext"); + + b.ToTable("JellyfinMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.ToTable("LocalMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("ClientIdentifier") + .HasColumnType("longtext"); + + b.Property("LastCollectionsScan") + .HasColumnType("datetime(6)"); + + b.Property("Platform") + .HasColumnType("longtext"); + + b.Property("PlatformVersion") + .HasColumnType("longtext"); + + b.Property("ProductVersion") + .HasColumnType("longtext"); + + b.Property("ServerName") + .HasColumnType("longtext"); + + b.ToTable("PlexMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("DiscardToFillAttempts") + .HasColumnType("int"); + + b.Property("PlayoutDuration") + .HasColumnType("time(6)"); + + b.Property("TailMode") + .HasColumnType("int"); + + b.ToTable("ProgramScheduleDurationItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleFloodItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("MultipleMode") + .HasColumnType("int"); + + b.ToTable("ProgramScheduleMultipleItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleOneItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("EmbyEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("JellyfinEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.ToTable("PlexEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("EmbyMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("JellyfinMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.ToTable("PlexMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexOtherVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.OtherVideo"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.ToTable("PlexOtherVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("EmbySeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("JellyfinSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.ToTable("PlexSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("EmbyShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("ItemId") + .HasColumnType("longtext"); + + b.ToTable("JellyfinShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.ToTable("PlexShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Actors") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Artwork", "Artwork") + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Actor", "ArtworkId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Actors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Actors") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Actors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Actors") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Actors") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Actors") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Actors") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Artwork"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("ArtistMetadata") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Channel", null) + .WithMany("Artwork") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Artwork") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Artwork") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockItem", "BlockItem") + .WithMany("BlockItemGraphicsElements") + .HasForeignKey("BlockItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("BlockItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockItem"); + + b.Navigation("GraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockItem", "BlockItem") + .WithMany("BlockItemWatermarks") + .HasForeignKey("BlockItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("BlockItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.HasOne("ErsatzTV.Core.Domain.FFmpegProfile", "FFmpegProfile") + .WithMany() + .HasForeignKey("FFmpegProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Channel", "MirrorSourceChannel") + .WithMany() + .HasForeignKey("MirrorSourceChannelId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany() + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("FFmpegProfile"); + + b.Navigation("FallbackFiller"); + + b.Navigation("MirrorSourceChannel"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("CollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("CollectionItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("DecoGraphicsElements") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("DecoGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("GraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("DecoWatermarks") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("DecoWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Directors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Directors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Directors") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Directors") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("Connections") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", "Episode") + .WithMany("EpisodeMetadata") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Episode"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.HasOne("ErsatzTV.Core.Domain.Resolution", "Resolution") + .WithMany() + .HasForeignKey("ResolutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resolution"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Genres") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Genres") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Genres") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Genres") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Genres") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Genres") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Genres") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Genres") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageFolderDuration", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "LibraryFolder") + .WithOne("ImageFolderDuration") + .HasForeignKey("ErsatzTV.Core.Domain.ImageFolderDuration", "LibraryFolderId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("LibraryFolder"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Image", "Image") + .WithMany("ImageMetadata") + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Image"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("Connections") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", "MediaSource") + .WithMany("Libraries") + .HasForeignKey("MediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("LibraryFolders") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("LibraryPath"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", "Library") + .WithMany("Paths") + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Library"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Chapters") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "LibraryFolder") + .WithMany("MediaFiles") + .HasForeignKey("LibraryFolderId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("MediaFiles") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryFolder"); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("MediaItems") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryPath"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Streams") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithMany("MediaVersions") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Image", null) + .WithMany("MediaVersions") + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithMany("MediaVersions") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStream", null) + .WithMany("MediaVersions") + .HasForeignKey("RemoteStreamId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Song", null) + .WithMany("MediaVersions") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Guids") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Guids") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Guids") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Guids") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Guids") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Guids") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Guids") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Guids") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Moods") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", "Movie") + .WithMany("MovieMetadata") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Movie"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("MultiCollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MultiCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoArtist", b => + { + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Artists") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", "MusicVideo") + .WithMany("MusicVideoMetadata") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MusicVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", "OtherVideo") + .WithMany("OtherVideoMetadata") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OtherVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlaylistGroup", "PlaylistGroup") + .WithMany("Playlists") + .HasForeignKey("PlaylistGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlaylistGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany("Items") + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.HasOne("ErsatzTV.Core.Domain.Channel", "Channel") + .WithMany("Playouts") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("Playouts") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Playouts") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.OwnsOne("ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 => + { + b1.Property("PlayoutId") + .HasColumnType("int"); + + b1.Property("Context") + .HasColumnType("longtext"); + + b1.Property("DurationFinish") + .HasColumnType("datetime(6)"); + + b1.Property("InDurationFiller") + .HasColumnType("tinyint(1)"); + + b1.Property("InFlood") + .HasColumnType("tinyint(1)"); + + b1.Property("MultipleRemaining") + .HasColumnType("int"); + + b1.Property("NextGuideGroup") + .HasColumnType("int"); + + b1.Property("NextInstructionIndex") + .HasColumnType("int"); + + b1.Property("NextStart") + .HasColumnType("datetime(6)"); + + b1.HasKey("PlayoutId"); + + b1.ToTable("PlayoutAnchor", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutId"); + + b1.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "ScheduleItemsEnumeratorState", b2 => + { + b2.Property("PlayoutAnchorPlayoutId") + .HasColumnType("int"); + + b2.Property("Index") + .HasColumnType("int"); + + b2.Property("Seed") + .HasColumnType("int"); + + b2.HasKey("PlayoutAnchorPlayoutId"); + + b2.ToTable("ScheduleItemsEnumeratorState", (string)null); + + b2.WithOwner() + .HasForeignKey("PlayoutAnchorPlayoutId"); + }); + + b1.Navigation("ScheduleItemsEnumeratorState"); + }); + + b.Navigation("Anchor"); + + b.Navigation("Channel"); + + b.Navigation("Deco"); + + b.Navigation("ProgramSchedule"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutBuildStatus", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithOne("BuildStatus") + .HasForeignKey("ErsatzTV.Core.Domain.PlayoutBuildStatus", "PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutGap", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Gaps") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Items") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("PlayoutItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.PlayoutItem", "PlayoutItem") + .WithMany("PlayoutItemGraphicsElements") + .HasForeignKey("PlayoutItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GraphicsElement"); + + b.Navigation("PlayoutItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlayoutItem", "PlayoutItem") + .WithMany("PlayoutItemWatermarks") + .HasForeignKey("PlayoutItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("PlayoutItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlayoutItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("ProgramScheduleAnchors") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => + { + b1.Property("PlayoutProgramScheduleAnchorId") + .HasColumnType("int"); + + b1.Property("Index") + .HasColumnType("int"); + + b1.Property("Seed") + .HasColumnType("int"); + + b1.HasKey("PlayoutProgramScheduleAnchorId"); + + b1.ToTable("CollectionEnumeratorState", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutProgramScheduleAnchorId"); + }); + + b.Navigation("Collection"); + + b.Navigation("EnumeratorState"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("Playout"); + + b.Navigation("RerunCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutScheduleItemFillGroupIndex", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("FillGroupIndices") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany() + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => + { + b1.Property("PlayoutScheduleItemFillGroupIndexId") + .HasColumnType("int"); + + b1.Property("Index") + .HasColumnType("int"); + + b1.Property("Seed") + .HasColumnType("int"); + + b1.HasKey("PlayoutScheduleItemFillGroupIndexId"); + + b1.ToTable("FillGroupEnumeratorState", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutScheduleItemFillGroupIndexId"); + }); + + b.Navigation("EnumeratorState"); + + b.Navigation("Playout"); + + b.Navigation("ProgramScheduleItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("Connections") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleAlternate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("ProgramScheduleAlternates") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("ProgramScheduleAlternates") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + + b.Navigation("ProgramSchedule"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "MidRollFiller") + .WithMany() + .HasForeignKey("MidRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PostRollFiller") + .WithMany() + .HasForeignKey("PostRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PreRollFiller") + .WithMany() + .HasForeignKey("PreRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Items") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "TailFiller") + .WithMany() + .HasForeignKey("TailFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Collection"); + + b.Navigation("FallbackFiller"); + + b.Navigation("MediaItem"); + + b.Navigation("MidRollFiller"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("PostRollFiller"); + + b.Navigation("PreRollFiller"); + + b.Navigation("ProgramSchedule"); + + b.Navigation("RerunCollection"); + + b.Navigation("SmartCollection"); + + b.Navigation("TailFiller"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("ProgramScheduleItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany("ProgramScheduleItemGraphicsElements") + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GraphicsElement"); + + b.Navigation("ProgramScheduleItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany("ProgramScheduleItemWatermarks") + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("ProgramScheduleItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProgramScheduleItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.RemoteStream", "RemoteStream") + .WithMany("RemoteStreamMetadata") + .HasForeignKey("RemoteStreamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RemoteStream"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RerunCollection", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockGroup", "BlockGroup") + .WithMany("Blocks") + .HasForeignKey("BlockGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("Items") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Block"); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "DeadAirFallbackCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DeadAirFallbackMediaItem") + .WithMany() + .HasForeignKey("DeadAirFallbackMediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DeadAirFallbackMultiCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackMultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DeadAirFallbackSmartCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackSmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoGroup", "DecoGroup") + .WithMany("Decos") + .HasForeignKey("DecoGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Collection", "DefaultFillerCollection") + .WithMany() + .HasForeignKey("DefaultFillerCollectionId"); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DefaultFillerMediaItem") + .WithMany() + .HasForeignKey("DefaultFillerMediaItemId"); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DefaultFillerMultiCollection") + .WithMany() + .HasForeignKey("DefaultFillerMultiCollectionId"); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DefaultFillerSmartCollection") + .WithMany() + .HasForeignKey("DefaultFillerSmartCollectionId"); + + b.Navigation("DeadAirFallbackCollection"); + + b.Navigation("DeadAirFallbackMediaItem"); + + b.Navigation("DeadAirFallbackMultiCollection"); + + b.Navigation("DeadAirFallbackSmartCollection"); + + b.Navigation("DecoGroup"); + + b.Navigation("DefaultFillerCollection"); + + b.Navigation("DefaultFillerMediaItem"); + + b.Navigation("DefaultFillerMultiCollection"); + + b.Navigation("DefaultFillerSmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoBreakContent", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("BreakContent") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("Deco"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", "DecoTemplateGroup") + .WithMany("DecoTemplates") + .HasForeignKey("DecoTemplateGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DecoTemplateGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany() + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", "DecoTemplate") + .WithMany("Items") + .HasForeignKey("DecoTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("DecoTemplate"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutHistory", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("PlayoutHistory") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("PlayoutHistory") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Block"); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutTemplate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", "DecoTemplate") + .WithMany("PlayoutTemplates") + .HasForeignKey("DecoTemplateId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Templates") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Template", "Template") + .WithMany("PlayoutTemplates") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DecoTemplate"); + + b.Navigation("Playout"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.RerunHistory", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany() + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("Playout"); + + b.Navigation("RerunCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", "TemplateGroup") + .WithMany("Templates") + .HasForeignKey("TemplateGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TemplateGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("TemplateItems") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Template", "Template") + .WithMany("Items") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Block"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("SeasonMetadata") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("ShowMetadata") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Song", "Song") + .WithMany("SongMetadata") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Song"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Studios") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Studios") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Studios") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Studios") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Studios") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Studios") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Studios") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Studios") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Styles") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Subtitle", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Tags") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Tags") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Tags") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Tags") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Tags") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Tags") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Tags") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Tags") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Playlist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("TraktListItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.TraktList", "TraktList") + .WithMany("Items") + .HasForeignKey("TraktListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("TraktList"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.TraktListItem", "TraktListItem") + .WithMany("Guids") + .HasForeignKey("TraktListItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TraktListItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Writers") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Writers") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Writers") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Emby.EmbyPathInfo", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyLibrary", null) + .WithMany("PathInfos") + .HasForeignKey("EmbyLibraryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Jellyfin.JellyfinPathInfo", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinLibrary", null) + .WithMany("PathInfos") + .HasForeignKey("JellyfinLibraryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaFile", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaFile", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Artist", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Episode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Image", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Movie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("MusicVideos") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.MusicVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.OtherVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.RemoteStream", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Season", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("Seasons") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Show", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Song", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemOne", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexOtherVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexOtherVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbySeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Moods"); + + b.Navigation("Studios"); + + b.Navigation("Styles"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Navigation("Artwork"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ChannelWatermark", b => + { + b.Navigation("BlockItemWatermarks"); + + b.Navigation("DecoWatermarks"); + + b.Navigation("PlayoutItemWatermarks"); + + b.Navigation("ProgramScheduleItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("MultiCollectionItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.GraphicsElement", b => + { + b.Navigation("BlockItemGraphicsElements"); + + b.Navigation("DecoGraphicsElements"); + + b.Navigation("PlayoutItemGraphicsElements"); + + b.Navigation("ProgramScheduleItemGraphicsElements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Navigation("Paths"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.Navigation("Children"); + + b.Navigation("ImageFolderDuration"); + + b.Navigation("MediaFiles"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Navigation("LibraryFolders"); + + b.Navigation("MediaItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("TraktListItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Navigation("Libraries"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Navigation("Chapters"); + + b.Navigation("MediaFiles"); + + b.Navigation("Streams"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Navigation("MultiCollectionItems"); + + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artists"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistGroup", b => + { + b.Navigation("Playlists"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Navigation("BuildStatus"); + + b.Navigation("FillGroupIndices"); + + b.Navigation("Gaps"); + + b.Navigation("Items"); + + b.Navigation("PlayoutHistory"); + + b.Navigation("ProgramScheduleAlternates"); + + b.Navigation("ProgramScheduleAnchors"); + + b.Navigation("Templates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.Navigation("PlayoutItemGraphicsElements"); + + b.Navigation("PlayoutItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Navigation("Items"); + + b.Navigation("Playouts"); + + b.Navigation("ProgramScheduleAlternates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.Navigation("ProgramScheduleItemGraphicsElements"); + + b.Navigation("ProgramScheduleItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutHistory"); + + b.Navigation("TemplateItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockGroup", b => + { + b.Navigation("Blocks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.Navigation("BlockItemGraphicsElements"); + + b.Navigation("BlockItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.Navigation("BreakContent"); + + b.Navigation("DecoGraphicsElements"); + + b.Navigation("DecoWatermarks"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoGroup", b => + { + b.Navigation("Decos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", b => + { + b.Navigation("DecoTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", b => + { + b.Navigation("Templates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Navigation("Guids"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.Navigation("PathInfos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.Navigation("PathInfos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.Navigation("ArtistMetadata"); + + b.Navigation("MusicVideos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.Navigation("EpisodeMetadata"); + + b.Navigation("MediaVersions"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.Navigation("ImageMetadata"); + + b.Navigation("MediaVersions"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MovieMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MusicVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("OtherVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("RemoteStreamMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.Navigation("Episodes"); + + b.Navigation("SeasonMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.Navigation("Seasons"); + + b.Navigation("ShowMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("SongMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.cs b/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.cs new file mode 100644 index 000000000..3c3a31d69 --- /dev/null +++ b/ErsatzTV.Infrastructure.MySql/Migrations/20251110043500_Add_MediaVersionInterlacedRatio.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ErsatzTV.Infrastructure.MySql.Migrations +{ + /// + public partial class Add_MediaVersionInterlacedRatio : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "InterlacedRatio", + table: "MediaVersion", + type: "double", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "InterlacedRatio", + table: "MediaVersion"); + } + } +} diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs b/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs index 7277db4a7..dc683ba0c 100644 --- a/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs +++ b/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs @@ -1393,6 +1393,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations b.Property("ImageId") .HasColumnType("int"); + b.Property("InterlacedRatio") + .HasColumnType("double"); + b.Property("MovieId") .HasColumnType("int"); diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.Designer.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.Designer.cs new file mode 100644 index 000000000..8c941ba4c --- /dev/null +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.Designer.cs @@ -0,0 +1,6697 @@ +// +using System; +using ErsatzTV.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ErsatzTV.Infrastructure.Sqlite.Migrations +{ + [DbContext(typeof(TvContext))] + [Migration("20251110043425_Add_MediaVersionInterlacedRatio")] + partial class Add_MediaVersionInterlacedRatio + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.10"); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ArtworkId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Role") + .HasColumnType("TEXT"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ArtworkId") + .IsUnique(); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Actor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("Biography") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("Disambiguation") + .HasColumnType("TEXT"); + + b.Property("Formed") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistId"); + + b.ToTable("ArtistMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ArtworkKind") + .HasColumnType("INTEGER"); + + b.Property("BlurHash43") + .HasColumnType("TEXT"); + + b.Property("BlurHash54") + .HasColumnType("TEXT"); + + b.Property("BlurHash64") + .HasColumnType("TEXT"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("OriginalContentType") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SourcePath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ChannelId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Artwork", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemGraphicsElement", b => + { + b.Property("BlockItemId") + .HasColumnType("INTEGER"); + + b.Property("GraphicsElementId") + .HasColumnType("INTEGER"); + + b.HasKey("BlockItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("BlockItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemWatermark", b => + { + b.Property("BlockItemId") + .HasColumnType("INTEGER"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("BlockItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("BlockItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Categories") + .HasColumnType("TEXT"); + + b.Property("FFmpegProfileId") + .HasColumnType("INTEGER"); + + b.Property("FallbackFillerId") + .HasColumnType("INTEGER"); + + b.Property("Group") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue("ErsatzTV"); + + b.Property("IdleBehavior") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("MirrorSourceChannelId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoCreditsMode") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoCreditsTemplate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("TEXT"); + + b.Property("PlayoutMode") + .HasColumnType("INTEGER"); + + b.Property("PlayoutOffset") + .HasColumnType("TEXT"); + + b.Property("PlayoutSource") + .HasColumnType("INTEGER"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("TEXT"); + + b.Property("PreferredAudioTitle") + .HasColumnType("TEXT"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("TEXT"); + + b.Property("ShowInEpg") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("SongVideoMode") + .HasColumnType("INTEGER"); + + b.Property("SortNumber") + .HasColumnType("REAL"); + + b.Property("StreamSelector") + .HasColumnType("TEXT"); + + b.Property("StreamSelectorMode") + .HasColumnType("INTEGER"); + + b.Property("StreamingMode") + .HasColumnType("INTEGER"); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("TranscodeMode") + .HasColumnType("INTEGER"); + + b.Property("UniqueId") + .HasColumnType("TEXT"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("FFmpegProfileId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("MirrorSourceChannelId"); + + b.HasIndex("Number") + .IsUnique(); + + b.HasIndex("WatermarkId"); + + b.ToTable("Channel", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ChannelWatermark", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DurationSeconds") + .HasColumnType("INTEGER"); + + b.Property("FrequencyMinutes") + .HasColumnType("INTEGER"); + + b.Property("HorizontalMarginPercent") + .HasColumnType("REAL"); + + b.Property("Image") + .HasColumnType("TEXT"); + + b.Property("ImageSource") + .HasColumnType("INTEGER"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("Mode") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Opacity") + .HasColumnType("INTEGER"); + + b.Property("OpacityExpression") + .HasColumnType("TEXT"); + + b.Property("OriginalContentType") + .HasColumnType("TEXT"); + + b.Property("PlaceWithinSourceContent") + .HasColumnType("INTEGER"); + + b.Property("Size") + .HasColumnType("INTEGER"); + + b.Property("VerticalMarginPercent") + .HasColumnType("REAL"); + + b.Property("WidthPercent") + .HasColumnType("REAL"); + + b.Property("ZIndex") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("ChannelWatermark", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UseCustomPlaybackOrder") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("CustomIndex") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "MediaItemId"); + + b.HasIndex("MediaItemId"); + + b.ToTable("CollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ConfigElement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("ConfigElement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoGraphicsElement", b => + { + b.Property("DecoId") + .HasColumnType("INTEGER"); + + b.Property("GraphicsElementId") + .HasColumnType("INTEGER"); + + b.HasKey("DecoId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("DecoGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoWatermark", b => + { + b.Property("DecoId") + .HasColumnType("INTEGER"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("DecoId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("DecoWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.ToTable("Director", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("EmbyMediaSourceId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EmbyMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("EmbyPath") + .HasColumnType("TEXT"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("EpisodeId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.ToTable("EpisodeMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowBFrames") + .HasColumnType("INTEGER"); + + b.Property("AudioBitrate") + .HasColumnType("INTEGER"); + + b.Property("AudioBufferSize") + .HasColumnType("INTEGER"); + + b.Property("AudioChannels") + .HasColumnType("INTEGER"); + + b.Property("AudioFormat") + .HasColumnType("INTEGER"); + + b.Property("AudioSampleRate") + .HasColumnType("INTEGER"); + + b.Property("BitDepth") + .HasColumnType("INTEGER"); + + b.Property("DeinterlaceVideo") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("HardwareAcceleration") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("NormalizeFramerate") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("NormalizeLoudnessMode") + .HasColumnType("INTEGER"); + + b.Property("QsvExtraHardwareFrames") + .HasColumnType("INTEGER"); + + b.Property("ResolutionId") + .HasColumnType("INTEGER"); + + b.Property("ScalingBehavior") + .HasColumnType("INTEGER"); + + b.Property("ThreadCount") + .HasColumnType("INTEGER"); + + b.Property("TonemapAlgorithm") + .HasColumnType("INTEGER"); + + b.Property("VaapiDevice") + .HasColumnType("TEXT"); + + b.Property("VaapiDisplay") + .HasColumnType("TEXT"); + + b.Property("VaapiDriver") + .HasColumnType("INTEGER"); + + b.Property("VideoBitrate") + .HasColumnType("INTEGER"); + + b.Property("VideoBufferSize") + .HasColumnType("INTEGER"); + + b.Property("VideoFormat") + .HasColumnType("INTEGER"); + + b.Property("VideoPreset") + .HasColumnType("TEXT"); + + b.Property("VideoProfile") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ResolutionId"); + + b.ToTable("FFmpegProfile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowWatermarks") + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("Expression") + .HasColumnType("TEXT"); + + b.Property("FillerKind") + .HasColumnType("INTEGER"); + + b.Property("FillerMode") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PadToNearestMinute") + .HasColumnType("INTEGER"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("UseChaptersAsMediaItems") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("FillerPreset", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Genre"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.GraphicsElement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("GraphicsElement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageFolderDuration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DurationSeconds") + .HasColumnType("REAL"); + + b.Property("LibraryFolderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LibraryFolderId") + .IsUnique(); + + b.ToTable("ImageFolderDuration", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("DurationSeconds") + .HasColumnType("REAL"); + + b.Property("ImageId") + .HasColumnType("INTEGER"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.ToTable("ImageMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("JellyfinPath") + .HasColumnType("TEXT"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LanguageCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EnglishName") + .HasColumnType("TEXT"); + + b.Property("FrenchName") + .HasColumnType("TEXT"); + + b.Property("ThreeCode1") + .HasColumnType("TEXT"); + + b.Property("ThreeCode2") + .HasColumnType("TEXT"); + + b.Property("TwoCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LanguageCode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastScan") + .HasColumnType("TEXT"); + + b.Property("MediaKind") + .HasColumnType("INTEGER"); + + b.Property("MediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaSourceId"); + + b.ToTable("Library", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("LibraryPathId") + .HasColumnType("INTEGER"); + + b.Property("ParentId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.HasIndex("ParentId"); + + b.ToTable("LibraryFolder", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastScan") + .HasColumnType("TEXT"); + + b.Property("LibraryId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryPath", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChapterId") + .HasColumnType("INTEGER"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaChapter", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LibraryFolderId") + .HasColumnType("INTEGER"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("PathHash") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LibraryFolderId"); + + b.HasIndex("MediaVersionId"); + + b.HasIndex("PathHash") + .IsUnique(); + + b.ToTable("MediaFile", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LibraryPathId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.ToTable("MediaItem", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("MediaSource", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AttachedPic") + .HasColumnType("INTEGER"); + + b.Property("BitsPerRawSample") + .HasColumnType("INTEGER"); + + b.Property("Channels") + .HasColumnType("INTEGER"); + + b.Property("Codec") + .HasColumnType("TEXT"); + + b.Property("ColorPrimaries") + .HasColumnType("TEXT"); + + b.Property("ColorRange") + .HasColumnType("TEXT"); + + b.Property("ColorSpace") + .HasColumnType("TEXT"); + + b.Property("ColorTransfer") + .HasColumnType("TEXT"); + + b.Property("Default") + .HasColumnType("INTEGER"); + + b.Property("FileName") + .HasColumnType("TEXT"); + + b.Property("Forced") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("MediaStreamKind") + .HasColumnType("INTEGER"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("PixelFormat") + .HasColumnType("TEXT"); + + b.Property("Profile") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaStream", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("DisplayAspectRatio") + .HasColumnType("TEXT"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("EpisodeId") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("ImageId") + .HasColumnType("INTEGER"); + + b.Property("InterlacedRatio") + .HasColumnType("REAL"); + + b.Property("MovieId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoId") + .HasColumnType("INTEGER"); + + b.Property("RFrameRate") + .HasColumnType("TEXT"); + + b.Property("RemoteStreamId") + .HasColumnType("INTEGER"); + + b.Property("SampleAspectRatio") + .HasColumnType("TEXT"); + + b.Property("SongId") + .HasColumnType("INTEGER"); + + b.Property("VideoScanKind") + .HasColumnType("INTEGER"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.HasIndex("ImageId"); + + b.HasIndex("MovieId"); + + b.HasIndex("MusicVideoId"); + + b.HasIndex("OtherVideoId"); + + b.HasIndex("RemoteStreamId"); + + b.HasIndex("SongId"); + + b.ToTable("MediaVersion", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Guid") + .HasColumnType("TEXT"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("MetadataGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Mood"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContentRating") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("MovieId") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MovieId"); + + b.ToTable("MovieMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MultiCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("ScheduleAsGroup") + .HasColumnType("INTEGER"); + + b.HasKey("MultiCollectionId", "CollectionId"); + + b.HasIndex("CollectionId"); + + b.ToTable("MultiCollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("ScheduleAsGroup") + .HasColumnType("INTEGER"); + + b.HasKey("MultiCollectionId", "SmartCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("MultiCollectionSmartItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoArtist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MusicVideoMetadataId"); + + b.ToTable("MusicVideoArtist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Album") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoId") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Track") + .HasColumnType("INTEGER"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MusicVideoId"); + + b.ToTable("MusicVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContentRating") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("OtherVideoId") + .HasColumnType("INTEGER"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OtherVideoId"); + + b.ToTable("OtherVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PlaylistGroupId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlaylistGroupId", "Name") + .IsUnique(); + + b.ToTable("Playlist", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PlaylistGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("IncludeInProgramGuide") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlayAll") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("PlaylistItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DailyRebuildTime") + .HasColumnType("TEXT"); + + b.Property("DecoId") + .HasColumnType("INTEGER"); + + b.Property("OnDemandCheckpoint") + .HasColumnType("TEXT"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.Property("ScheduleFile") + .HasColumnType("TEXT"); + + b.Property("ScheduleKind") + .HasColumnType("INTEGER"); + + b.Property("Seed") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("DecoId"); + + b.HasIndex("ProgramScheduleId"); + + b.ToTable("Playout", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutBuildStatus", b => + { + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("LastBuild") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Success") + .HasColumnType("INTEGER"); + + b.HasKey("PlayoutId"); + + b.ToTable("PlayoutBuildStatus", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutGap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Finish") + .HasColumnType("TEXT"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("Start") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("Start", "Finish") + .HasDatabaseName("IX_PlayoutGap_Start_Finish"); + + b.ToTable("PlayoutGap", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BlockKey") + .HasColumnType("TEXT"); + + b.Property("ChapterTitle") + .HasColumnType("TEXT"); + + b.Property("CollectionEtag") + .HasColumnType("TEXT"); + + b.Property("CollectionKey") + .HasColumnType("TEXT"); + + b.Property("CustomTitle") + .HasColumnType("TEXT"); + + b.Property("DisableWatermarks") + .HasColumnType("INTEGER"); + + b.Property("FillerKind") + .HasColumnType("INTEGER"); + + b.Property("Finish") + .HasColumnType("TEXT"); + + b.Property("GuideFinish") + .HasColumnType("TEXT"); + + b.Property("GuideGroup") + .HasColumnType("INTEGER"); + + b.Property("GuideStart") + .HasColumnType("TEXT"); + + b.Property("InPoint") + .HasColumnType("TEXT"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("OutPoint") + .HasColumnType("TEXT"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("TEXT"); + + b.Property("PreferredAudioTitle") + .HasColumnType("TEXT"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("TEXT"); + + b.Property("Start") + .HasColumnType("TEXT"); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("Start", "Finish") + .HasDatabaseName("IX_PlayoutItem_Start_Finish"); + + b.ToTable("PlayoutItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemGraphicsElement", b => + { + b.Property("PlayoutItemId") + .HasColumnType("INTEGER"); + + b.Property("GraphicsElementId") + .HasColumnType("INTEGER"); + + b.Property("Variables") + .HasColumnType("TEXT"); + + b.HasKey("PlayoutItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("PlayoutItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemWatermark", b => + { + b.Property("PlayoutItemId") + .HasColumnType("INTEGER"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("PlayoutItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("PlayoutItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AnchorDate") + .HasColumnType("TEXT"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("FakeCollectionKey") + .HasColumnType("TEXT"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("RerunCollectionId") + .HasColumnType("INTEGER"); + + b.Property("SearchQuery") + .HasColumnType("TEXT"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("RerunCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("PlayoutProgramScheduleAnchor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutScheduleItemFillGroupIndex", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("ProgramScheduleItemId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("ProgramScheduleItemId"); + + b.ToTable("PlayoutScheduleItemFillGroupIndex", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("PlexMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.Property("PlexMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("PlexPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("FixedStartTimeBehavior") + .HasColumnType("INTEGER"); + + b.Property("KeepMultiPartEpisodesTogether") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RandomStartPoint") + .HasColumnType("INTEGER"); + + b.Property("ShuffleScheduleItems") + .HasColumnType("INTEGER"); + + b.Property("TreatCollectionsAsShows") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("ProgramSchedule", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleAlternate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DaysOfMonth") + .HasColumnType("TEXT"); + + b.Property("DaysOfWeek") + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MonthsOfYear") + .HasColumnType("TEXT"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("ProgramScheduleId"); + + b.ToTable("ProgramScheduleAlternate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("CustomTitle") + .HasColumnType("TEXT"); + + b.Property("FakeCollectionKey") + .HasColumnType("TEXT"); + + b.Property("FallbackFillerId") + .HasColumnType("INTEGER"); + + b.Property("FillWithGroupMode") + .HasColumnType("INTEGER"); + + b.Property("FixedStartTimeBehavior") + .HasColumnType("INTEGER"); + + b.Property("GuideMode") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MarathonBatchSize") + .HasColumnType("INTEGER"); + + b.Property("MarathonGroupBy") + .HasColumnType("INTEGER"); + + b.Property("MarathonShuffleGroups") + .HasColumnType("INTEGER"); + + b.Property("MarathonShuffleItems") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MidRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("PostRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("PreRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("PreferredAudioLanguageCode") + .HasColumnType("TEXT"); + + b.Property("PreferredAudioTitle") + .HasColumnType("TEXT"); + + b.Property("PreferredSubtitleLanguageCode") + .HasColumnType("TEXT"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.Property("RerunCollectionId") + .HasColumnType("INTEGER"); + + b.Property("SearchQuery") + .HasColumnType("TEXT"); + + b.Property("SearchTitle") + .HasColumnType("TEXT"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("TailFillerId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MidRollFillerId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("PostRollFillerId"); + + b.HasIndex("PreRollFillerId"); + + b.HasIndex("ProgramScheduleId"); + + b.HasIndex("RerunCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.HasIndex("TailFillerId"); + + b.ToTable("ProgramScheduleItem", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemGraphicsElement", b => + { + b.Property("ProgramScheduleItemId") + .HasColumnType("INTEGER"); + + b.Property("GraphicsElementId") + .HasColumnType("INTEGER"); + + b.HasKey("ProgramScheduleItemId", "GraphicsElementId"); + + b.HasIndex("GraphicsElementId"); + + b.ToTable("ProgramScheduleItemGraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemWatermark", b => + { + b.Property("ProgramScheduleItemId") + .HasColumnType("INTEGER"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("ProgramScheduleItemId", "WatermarkId"); + + b.HasIndex("WatermarkId"); + + b.ToTable("ProgramScheduleItemWatermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RemoteStreamId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("RemoteStreamId"); + + b.ToTable("RemoteStreamMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RerunCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("FirstRunPlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RerunPlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("RerunCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Resolution", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("IsCustom") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Resolution", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BlockGroupId") + .HasColumnType("INTEGER"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("Minutes") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("StopScheduling") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BlockGroupId", "Name") + .IsUnique(); + + b.ToTable("Block", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("BlockGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BlockId") + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("DisableWatermarks") + .HasColumnType("INTEGER"); + + b.Property("IncludeInProgramGuide") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("BlockItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BreakContentMode") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackCollectionType") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackMediaItemId") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackMode") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackMultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DeadAirFallbackSmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DecoGroupId") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerCollectionType") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerMediaItemId") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerMode") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerMultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerSmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("DefaultFillerTrimToFit") + .HasColumnType("INTEGER"); + + b.Property("GraphicsElementsMode") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UseGraphicsElementsDuringFiller") + .HasColumnType("INTEGER"); + + b.Property("UseWatermarkDuringFiller") + .HasColumnType("INTEGER"); + + b.Property("WatermarkMode") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DeadAirFallbackCollectionId"); + + b.HasIndex("DeadAirFallbackMediaItemId"); + + b.HasIndex("DeadAirFallbackMultiCollectionId"); + + b.HasIndex("DeadAirFallbackSmartCollectionId"); + + b.HasIndex("DefaultFillerCollectionId"); + + b.HasIndex("DefaultFillerMediaItemId"); + + b.HasIndex("DefaultFillerMultiCollectionId"); + + b.HasIndex("DefaultFillerSmartCollectionId"); + + b.HasIndex("DecoGroupId", "Name") + .IsUnique(); + + b.ToTable("Deco", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoBreakContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("DecoId") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("Placement") + .HasColumnType("INTEGER"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("DecoId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("DecoBreakContent", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("DecoGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("DecoTemplateGroupId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DecoTemplateGroupId", "Name") + .IsUnique(); + + b.ToTable("DecoTemplate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("DecoTemplateGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DecoId") + .HasColumnType("INTEGER"); + + b.Property("DecoTemplateId") + .HasColumnType("INTEGER"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DecoId"); + + b.HasIndex("DecoTemplateId"); + + b.ToTable("DecoTemplateItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BlockId") + .HasColumnType("INTEGER"); + + b.Property("ChildKey") + .HasColumnType("TEXT"); + + b.Property("Details") + .HasColumnType("TEXT"); + + b.Property("Finish") + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCurrentChild") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("PlayoutId"); + + b.ToTable("PlayoutHistory", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("DaysOfMonth") + .HasColumnType("TEXT"); + + b.Property("DaysOfWeek") + .HasColumnType("TEXT"); + + b.Property("DecoTemplateId") + .HasColumnType("INTEGER"); + + b.Property("EndDay") + .HasColumnType("INTEGER"); + + b.Property("EndMonth") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("LimitToDateRange") + .HasColumnType("INTEGER"); + + b.Property("MonthsOfYear") + .HasColumnType("TEXT"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("StartDay") + .HasColumnType("INTEGER"); + + b.Property("StartMonth") + .HasColumnType("INTEGER"); + + b.Property("TemplateId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DecoTemplateId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("TemplateId"); + + b.ToTable("PlayoutTemplate", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.RerunHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("RerunCollectionId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("RerunCollectionId"); + + b.ToTable("RerunHistory", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("TemplateGroupId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("TemplateGroupId", "Name") + .IsUnique(); + + b.ToTable("Template", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("TemplateGroup", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BlockId") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("TemplateId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BlockId"); + + b.HasIndex("TemplateId"); + + b.ToTable("TemplateItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("SeasonMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContentRating") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ShowId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ShowId"); + + b.ToTable("ShowMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SmartCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Album") + .HasColumnType("TEXT"); + + b.PrimitiveCollection("AlbumArtists") + .HasColumnType("TEXT"); + + b.PrimitiveCollection("Artists") + .HasColumnType("TEXT"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SongId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Track") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SongId"); + + b.ToTable("SongMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Studio", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Style"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Subtitle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Codec") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("Default") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Forced") + .HasColumnType("INTEGER"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("IsExtracted") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SDH") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.Property("StreamIndex") + .HasColumnType("INTEGER"); + + b.Property("SubtitleKind") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Subtitle", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ExternalCollectionId") + .HasColumnType("TEXT"); + + b.Property("ExternalTypeId") + .HasColumnType("TEXT"); + + b.Property("ImageMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("RemoteStreamMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("ImageMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("RemoteStreamMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Tag"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRefresh") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("GeneratePlaylist") + .HasColumnType("INTEGER"); + + b.Property("ItemCount") + .HasColumnType("INTEGER"); + + b.Property("LastMatch") + .HasColumnType("TEXT"); + + b.Property("LastUpdate") + .HasColumnType("TEXT"); + + b.Property("List") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PlaylistId") + .HasColumnType("INTEGER"); + + b.Property("TraktId") + .HasColumnType("INTEGER"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlaylistId"); + + b.ToTable("TraktList", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Episode") + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("Season") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TraktId") + .HasColumnType("INTEGER"); + + b.Property("TraktListId") + .HasColumnType("INTEGER"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("TraktListId"); + + b.ToTable("TraktListItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Guid") + .HasColumnType("TEXT"); + + b.Property("TraktListItemId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("TraktListItemId"); + + b.ToTable("TraktListItemGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.ToTable("Writer", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Emby.EmbyPathInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EmbyLibraryId") + .HasColumnType("INTEGER"); + + b.Property("NetworkPath") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EmbyLibraryId"); + + b.ToTable("EmbyPathInfo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Jellyfin.JellyfinPathInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("JellyfinLibraryId") + .HasColumnType("INTEGER"); + + b.Property("NetworkPath") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinLibraryId"); + + b.ToTable("JellyfinPathInfo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("EmbyLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("JellyfinLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.ToTable("LocalLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("LastNetworksScan") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("PlexLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaFile"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("PlexId") + .HasColumnType("INTEGER"); + + b.ToTable("PlexMediaFile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Artist", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.HasIndex("SeasonId"); + + b.ToTable("Episode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Image", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Movie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.HasIndex("ArtistId"); + + b.ToTable("MusicVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("OtherVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("FallbackQuery") + .HasColumnType("TEXT"); + + b.Property("IsLive") + .HasColumnType("INTEGER"); + + b.Property("Script") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.ToTable("RemoteStream", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("ShowId") + .HasColumnType("INTEGER"); + + b.HasIndex("ShowId"); + + b.ToTable("Season", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Show", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Song", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("LastCollectionsScan") + .HasColumnType("TEXT"); + + b.Property("OperatingSystem") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("EmbyMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("LastCollectionsScan") + .HasColumnType("TEXT"); + + b.Property("OperatingSystem") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.ToTable("LocalMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("ClientIdentifier") + .HasColumnType("TEXT"); + + b.Property("LastCollectionsScan") + .HasColumnType("TEXT"); + + b.Property("Platform") + .HasColumnType("TEXT"); + + b.Property("PlatformVersion") + .HasColumnType("TEXT"); + + b.Property("ProductVersion") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("PlexMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("DiscardToFillAttempts") + .HasColumnType("INTEGER"); + + b.Property("PlayoutDuration") + .HasColumnType("TEXT"); + + b.Property("TailMode") + .HasColumnType("INTEGER"); + + b.ToTable("ProgramScheduleDurationItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleFloodItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("MultipleMode") + .HasColumnType("INTEGER"); + + b.ToTable("ProgramScheduleMultipleItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleOneItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexOtherVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.OtherVideo"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexOtherVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbySeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Actors") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Artwork", "Artwork") + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Actor", "ArtworkId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Actors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Actors") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Actors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Actors") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Actors") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Actors") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Actors") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Artwork"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("ArtistMetadata") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Channel", null) + .WithMany("Artwork") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Artwork") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Artwork") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockItem", "BlockItem") + .WithMany("BlockItemGraphicsElements") + .HasForeignKey("BlockItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("BlockItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockItem"); + + b.Navigation("GraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.BlockItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockItem", "BlockItem") + .WithMany("BlockItemWatermarks") + .HasForeignKey("BlockItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("BlockItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.HasOne("ErsatzTV.Core.Domain.FFmpegProfile", "FFmpegProfile") + .WithMany() + .HasForeignKey("FFmpegProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Channel", "MirrorSourceChannel") + .WithMany() + .HasForeignKey("MirrorSourceChannelId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany() + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("FFmpegProfile"); + + b.Navigation("FallbackFiller"); + + b.Navigation("MirrorSourceChannel"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("CollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("CollectionItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("DecoGraphicsElements") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("DecoGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("GraphicsElement"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.DecoWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("DecoWatermarks") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("DecoWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Directors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Directors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Directors") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Directors") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("Connections") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", "Episode") + .WithMany("EpisodeMetadata") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Episode"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.HasOne("ErsatzTV.Core.Domain.Resolution", "Resolution") + .WithMany() + .HasForeignKey("ResolutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resolution"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Genres") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Genres") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Genres") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Genres") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Genres") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Genres") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Genres") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Genres") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageFolderDuration", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "LibraryFolder") + .WithOne("ImageFolderDuration") + .HasForeignKey("ErsatzTV.Core.Domain.ImageFolderDuration", "LibraryFolderId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("LibraryFolder"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Image", "Image") + .WithMany("ImageMetadata") + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Image"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("Connections") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", "MediaSource") + .WithMany("Libraries") + .HasForeignKey("MediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("LibraryFolders") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("LibraryPath"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", "Library") + .WithMany("Paths") + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Library"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Chapters") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryFolder", "LibraryFolder") + .WithMany("MediaFiles") + .HasForeignKey("LibraryFolderId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("MediaFiles") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryFolder"); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("MediaItems") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryPath"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Streams") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithMany("MediaVersions") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Image", null) + .WithMany("MediaVersions") + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithMany("MediaVersions") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStream", null) + .WithMany("MediaVersions") + .HasForeignKey("RemoteStreamId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Song", null) + .WithMany("MediaVersions") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Guids") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Guids") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Guids") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Guids") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Guids") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Guids") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Guids") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Guids") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Moods") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", "Movie") + .WithMany("MovieMetadata") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Movie"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("MultiCollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MultiCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoArtist", b => + { + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Artists") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", "MusicVideo") + .WithMany("MusicVideoMetadata") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MusicVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", "OtherVideo") + .WithMany("OtherVideoMetadata") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OtherVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlaylistGroup", "PlaylistGroup") + .WithMany("Playlists") + .HasForeignKey("PlaylistGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlaylistGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany("Items") + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.HasOne("ErsatzTV.Core.Domain.Channel", "Channel") + .WithMany("Playouts") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("Playouts") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Playouts") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.OwnsOne("ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 => + { + b1.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b1.Property("Context") + .HasColumnType("TEXT"); + + b1.Property("DurationFinish") + .HasColumnType("TEXT"); + + b1.Property("InDurationFiller") + .HasColumnType("INTEGER"); + + b1.Property("InFlood") + .HasColumnType("INTEGER"); + + b1.Property("MultipleRemaining") + .HasColumnType("INTEGER"); + + b1.Property("NextGuideGroup") + .HasColumnType("INTEGER"); + + b1.Property("NextInstructionIndex") + .HasColumnType("INTEGER"); + + b1.Property("NextStart") + .HasColumnType("TEXT"); + + b1.HasKey("PlayoutId"); + + b1.ToTable("PlayoutAnchor", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutId"); + + b1.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "ScheduleItemsEnumeratorState", b2 => + { + b2.Property("PlayoutAnchorPlayoutId") + .HasColumnType("INTEGER"); + + b2.Property("Index") + .HasColumnType("INTEGER"); + + b2.Property("Seed") + .HasColumnType("INTEGER"); + + b2.HasKey("PlayoutAnchorPlayoutId"); + + b2.ToTable("ScheduleItemsEnumeratorState", (string)null); + + b2.WithOwner() + .HasForeignKey("PlayoutAnchorPlayoutId"); + }); + + b1.Navigation("ScheduleItemsEnumeratorState"); + }); + + b.Navigation("Anchor"); + + b.Navigation("Channel"); + + b.Navigation("Deco"); + + b.Navigation("ProgramSchedule"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutBuildStatus", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithOne("BuildStatus") + .HasForeignKey("ErsatzTV.Core.Domain.PlayoutBuildStatus", "PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutGap", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Gaps") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Items") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("PlayoutItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.PlayoutItem", "PlayoutItem") + .WithMany("PlayoutItemGraphicsElements") + .HasForeignKey("PlayoutItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GraphicsElement"); + + b.Navigation("PlayoutItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlayoutItem", "PlayoutItem") + .WithMany("PlayoutItemWatermarks") + .HasForeignKey("PlayoutItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("PlayoutItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlayoutItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("ProgramScheduleAnchors") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => + { + b1.Property("PlayoutProgramScheduleAnchorId") + .HasColumnType("INTEGER"); + + b1.Property("Index") + .HasColumnType("INTEGER"); + + b1.Property("Seed") + .HasColumnType("INTEGER"); + + b1.HasKey("PlayoutProgramScheduleAnchorId"); + + b1.ToTable("CollectionEnumeratorState", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutProgramScheduleAnchorId"); + }); + + b.Navigation("Collection"); + + b.Navigation("EnumeratorState"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("Playout"); + + b.Navigation("RerunCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutScheduleItemFillGroupIndex", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("FillGroupIndices") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany() + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => + { + b1.Property("PlayoutScheduleItemFillGroupIndexId") + .HasColumnType("INTEGER"); + + b1.Property("Index") + .HasColumnType("INTEGER"); + + b1.Property("Seed") + .HasColumnType("INTEGER"); + + b1.HasKey("PlayoutScheduleItemFillGroupIndexId"); + + b1.ToTable("FillGroupEnumeratorState", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutScheduleItemFillGroupIndexId"); + }); + + b.Navigation("EnumeratorState"); + + b.Navigation("Playout"); + + b.Navigation("ProgramScheduleItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("Connections") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleAlternate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("ProgramScheduleAlternates") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("ProgramScheduleAlternates") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Playout"); + + b.Navigation("ProgramSchedule"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "MidRollFiller") + .WithMany() + .HasForeignKey("MidRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PostRollFiller") + .WithMany() + .HasForeignKey("PostRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PreRollFiller") + .WithMany() + .HasForeignKey("PreRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Items") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "TailFiller") + .WithMany() + .HasForeignKey("TailFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Collection"); + + b.Navigation("FallbackFiller"); + + b.Navigation("MediaItem"); + + b.Navigation("MidRollFiller"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("PostRollFiller"); + + b.Navigation("PreRollFiller"); + + b.Navigation("ProgramSchedule"); + + b.Navigation("RerunCollection"); + + b.Navigation("SmartCollection"); + + b.Navigation("TailFiller"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemGraphicsElement", b => + { + b.HasOne("ErsatzTV.Core.Domain.GraphicsElement", "GraphicsElement") + .WithMany("ProgramScheduleItemGraphicsElements") + .HasForeignKey("GraphicsElementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany("ProgramScheduleItemGraphicsElements") + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GraphicsElement"); + + b.Navigation("ProgramScheduleItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemWatermark", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "ProgramScheduleItem") + .WithMany("ProgramScheduleItemWatermarks") + .HasForeignKey("ProgramScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany("ProgramScheduleItemWatermarks") + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProgramScheduleItem"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.RemoteStream", "RemoteStream") + .WithMany("RemoteStreamMetadata") + .HasForeignKey("RemoteStreamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RemoteStream"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RerunCollection", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.BlockGroup", "BlockGroup") + .WithMany("Blocks") + .HasForeignKey("BlockGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("Items") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Block"); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "DeadAirFallbackCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DeadAirFallbackMediaItem") + .WithMany() + .HasForeignKey("DeadAirFallbackMediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DeadAirFallbackMultiCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackMultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DeadAirFallbackSmartCollection") + .WithMany() + .HasForeignKey("DeadAirFallbackSmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoGroup", "DecoGroup") + .WithMany("Decos") + .HasForeignKey("DecoGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Collection", "DefaultFillerCollection") + .WithMany() + .HasForeignKey("DefaultFillerCollectionId"); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DefaultFillerMediaItem") + .WithMany() + .HasForeignKey("DefaultFillerMediaItemId"); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DefaultFillerMultiCollection") + .WithMany() + .HasForeignKey("DefaultFillerMultiCollectionId"); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DefaultFillerSmartCollection") + .WithMany() + .HasForeignKey("DefaultFillerSmartCollectionId"); + + b.Navigation("DeadAirFallbackCollection"); + + b.Navigation("DeadAirFallbackMediaItem"); + + b.Navigation("DeadAirFallbackMultiCollection"); + + b.Navigation("DeadAirFallbackSmartCollection"); + + b.Navigation("DecoGroup"); + + b.Navigation("DefaultFillerCollection"); + + b.Navigation("DefaultFillerMediaItem"); + + b.Navigation("DefaultFillerMultiCollection"); + + b.Navigation("DefaultFillerSmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoBreakContent", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany("BreakContent") + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("Deco"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playlist"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", "DecoTemplateGroup") + .WithMany("DecoTemplates") + .HasForeignKey("DecoTemplateGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DecoTemplateGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Deco", "Deco") + .WithMany() + .HasForeignKey("DecoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", "DecoTemplate") + .WithMany("Items") + .HasForeignKey("DecoTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deco"); + + b.Navigation("DecoTemplate"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutHistory", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("PlayoutHistory") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("PlayoutHistory") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Block"); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.PlayoutTemplate", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", "DecoTemplate") + .WithMany("PlayoutTemplates") + .HasForeignKey("DecoTemplateId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Templates") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Template", "Template") + .WithMany("PlayoutTemplates") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DecoTemplate"); + + b.Navigation("Playout"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.RerunHistory", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany() + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.RerunCollection", "RerunCollection") + .WithMany() + .HasForeignKey("RerunCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("Playout"); + + b.Navigation("RerunCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", "TemplateGroup") + .WithMany("Templates") + .HasForeignKey("TemplateGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TemplateGroup"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Block", "Block") + .WithMany("TemplateItems") + .HasForeignKey("BlockId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Scheduling.Template", "Template") + .WithMany("Items") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Block"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("SeasonMetadata") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("ShowMetadata") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Song", "Song") + .WithMany("SongMetadata") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Song"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Studios") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Studios") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Studios") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Studios") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Studios") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Studios") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Studios") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Studios") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Styles") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Subtitle", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Subtitles") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Tags") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Tags") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ImageMetadata", null) + .WithMany("Tags") + .HasForeignKey("ImageMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Tags") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.RemoteStreamMetadata", null) + .WithMany("Tags") + .HasForeignKey("RemoteStreamMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Tags") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Tags") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Tags") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist") + .WithMany() + .HasForeignKey("PlaylistId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Playlist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("TraktListItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.TraktList", "TraktList") + .WithMany("Items") + .HasForeignKey("TraktListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("TraktList"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.TraktListItem", "TraktListItem") + .WithMany("Guids") + .HasForeignKey("TraktListItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TraktListItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Writers") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Writers") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Writers") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Emby.EmbyPathInfo", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyLibrary", null) + .WithMany("PathInfos") + .HasForeignKey("EmbyLibraryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Jellyfin.JellyfinPathInfo", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinLibrary", null) + .WithMany("PathInfos") + .HasForeignKey("JellyfinLibraryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaFile", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaFile", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Artist", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Episode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Image", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Movie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("MusicVideos") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.MusicVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.OtherVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.RemoteStream", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Season", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("Seasons") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Show", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Song", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemOne", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexOtherVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexOtherVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbySeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Moods"); + + b.Navigation("Studios"); + + b.Navigation("Styles"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Navigation("Artwork"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ChannelWatermark", b => + { + b.Navigation("BlockItemWatermarks"); + + b.Navigation("DecoWatermarks"); + + b.Navigation("PlayoutItemWatermarks"); + + b.Navigation("ProgramScheduleItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("MultiCollectionItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.GraphicsElement", b => + { + b.Navigation("BlockItemGraphicsElements"); + + b.Navigation("DecoGraphicsElements"); + + b.Navigation("PlayoutItemGraphicsElements"); + + b.Navigation("ProgramScheduleItemGraphicsElements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ImageMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Navigation("Paths"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.Navigation("Children"); + + b.Navigation("ImageFolderDuration"); + + b.Navigation("MediaFiles"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Navigation("LibraryFolders"); + + b.Navigation("MediaItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("TraktListItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Navigation("Libraries"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Navigation("Chapters"); + + b.Navigation("MediaFiles"); + + b.Navigation("Streams"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Navigation("MultiCollectionItems"); + + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artists"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playlist", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlaylistGroup", b => + { + b.Navigation("Playlists"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Navigation("BuildStatus"); + + b.Navigation("FillGroupIndices"); + + b.Navigation("Gaps"); + + b.Navigation("Items"); + + b.Navigation("PlayoutHistory"); + + b.Navigation("ProgramScheduleAlternates"); + + b.Navigation("ProgramScheduleAnchors"); + + b.Navigation("Templates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.Navigation("PlayoutItemGraphicsElements"); + + b.Navigation("PlayoutItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Navigation("Items"); + + b.Navigation("Playouts"); + + b.Navigation("ProgramScheduleAlternates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.Navigation("ProgramScheduleItemGraphicsElements"); + + b.Navigation("ProgramScheduleItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStreamMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Block", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutHistory"); + + b.Navigation("TemplateItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockGroup", b => + { + b.Navigation("Blocks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.BlockItem", b => + { + b.Navigation("BlockItemGraphicsElements"); + + b.Navigation("BlockItemWatermarks"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b => + { + b.Navigation("BreakContent"); + + b.Navigation("DecoGraphicsElements"); + + b.Navigation("DecoWatermarks"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoGroup", b => + { + b.Navigation("Decos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplate", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.DecoTemplateGroup", b => + { + b.Navigation("DecoTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Template", b => + { + b.Navigation("Items"); + + b.Navigation("PlayoutTemplates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.TemplateGroup", b => + { + b.Navigation("Templates"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Subtitles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Navigation("Guids"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.Navigation("PathInfos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.Navigation("PathInfos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.Navigation("ArtistMetadata"); + + b.Navigation("MusicVideos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.Navigation("EpisodeMetadata"); + + b.Navigation("MediaVersions"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Image", b => + { + b.Navigation("ImageMetadata"); + + b.Navigation("MediaVersions"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MovieMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MusicVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("OtherVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.RemoteStream", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("RemoteStreamMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.Navigation("Episodes"); + + b.Navigation("SeasonMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.Navigation("Seasons"); + + b.Navigation("ShowMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("SongMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.cs new file mode 100644 index 000000000..ab1d5336b --- /dev/null +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/20251110043425_Add_MediaVersionInterlacedRatio.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ErsatzTV.Infrastructure.Sqlite.Migrations +{ + /// + public partial class Add_MediaVersionInterlacedRatio : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "InterlacedRatio", + table: "MediaVersion", + type: "REAL", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "InterlacedRatio", + table: "MediaVersion"); + } + } +} diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs index baa1188e3..ec3bf30a7 100644 --- a/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs @@ -1326,6 +1326,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations b.Property("ImageId") .HasColumnType("INTEGER"); + b.Property("InterlacedRatio") + .HasColumnType("REAL"); + b.Property("MovieId") .HasColumnType("INTEGER"); diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs index f1b77fc09..5ee0139da 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs @@ -112,6 +112,18 @@ public class MediaItemRepository : IMediaItemRepository .Map(list => list.ToImmutableHashSet()); } + public async Task SetInterlacedRatio(MediaItem mediaItem, double interlacedRatio) + { + await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); + + var mediaVersion = mediaItem.GetHeadVersion(); + mediaVersion.InterlacedRatio = interlacedRatio; + + await dbContext.Connection.ExecuteAsync( + @"UPDATE MediaVersion SET InterlacedRatio = @InterlacedRatio WHERE Id = @Id", + new { mediaVersion.Id, InterlacedRatio = interlacedRatio }); + } + public async Task FlagNormal(MediaItem mediaItem) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MetadataRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MetadataRepository.cs index c7f1342c3..b3bb60ac3 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MetadataRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MetadataRepository.cs @@ -137,6 +137,7 @@ public class MetadataRepository(IDbContextFactory dbContextFactory) : existing.Width = incoming.Width; existing.Height = incoming.Height; existing.VideoScanKind = incoming.VideoScanKind; + existing.InterlacedRatio = incoming.InterlacedRatio; existing.RFrameRate = incoming.RFrameRate; } diff --git a/ErsatzTV.Infrastructure/Metadata/LocalStatisticsProvider.cs b/ErsatzTV.Infrastructure/Metadata/LocalStatisticsProvider.cs index cd14d2218..e09b982df 100644 --- a/ErsatzTV.Infrastructure/Metadata/LocalStatisticsProvider.cs +++ b/ErsatzTV.Infrastructure/Metadata/LocalStatisticsProvider.cs @@ -18,7 +18,7 @@ using File = TagLib.File; namespace ErsatzTV.Infrastructure.Metadata; -public class LocalStatisticsProvider : ILocalStatisticsProvider +public partial class LocalStatisticsProvider : ILocalStatisticsProvider { private readonly IClient _client; private readonly IHardwareCapabilitiesFactory _hardwareCapabilitiesFactory; @@ -131,6 +131,52 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider } } + public async Task> GetInterlacedRatio( + string ffmpegPath, + MediaItem mediaItem, + CancellationToken cancellationToken) + { + try + { + string filePath = await PathForMediaItem(mediaItem); + + if (Path.GetExtension(filePath) == ".avs" && !_hardwareCapabilitiesFactory.IsAviSynthInstalled()) + { + return Option.None; + } + + if (filePath.StartsWith("http", StringComparison.OrdinalIgnoreCase) || + !_localFileSystem.FileExists(filePath)) + { + _logger.LogDebug("Skipping interlaced ratio check for remote content"); + return Option.None; + } + + var duration = mediaItem.GetDurationForPlayout(); + if (duration < TimeSpan.FromSeconds(3)) + { + return Option.None; + } + + Option maybeStats = await GetIdetOutput(ffmpegPath, filePath, duration / 3); + foreach (var stats in maybeStats) + { + if (stats.TotalFrames == 0) + { + return 0; + } + + return (double)stats.TotalInterlacedFrames / stats.TotalInterlacedFrames; + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to check interlaced ratio for media item {Id}", mediaItem.Id); + } + + return Option.None; + } + private async Task> RefreshStatistics( string ffmpegPath, string ffprobePath, @@ -200,8 +246,7 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider FFprobe ffprobe = JsonConvert.DeserializeObject(probe.StandardOutput); if (ffprobe is not null) { - const string PATTERN = @"\[SAR\s+([0-9]+:[0-9]+)\s+DAR\s+([0-9]+:[0-9]+)\]"; - Match match = Regex.Match(probe.StandardError, PATTERN); + Match match = SarDarRegex().Match(probe.StandardError); if (match.Success) { string sar = match.Groups[1].Value; @@ -234,6 +279,55 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider return BaseError.New("Unable to deserialize ffprobe output"); } + private async Task> GetIdetOutput(string ffmpegPath, string filePath, TimeSpan seek) + { + string[] arguments = + [ + "-hide_banner", + "-ss", $"{seek:c}", + "-i", filePath, + "-vf", "idet", + "-frames:v", "200", + "-an", + "-f", "null", "-" + ]; + + BufferedCommandResult idet = await Cli.Wrap(ffmpegPath) + .WithArguments(arguments) + .WithValidation(CommandResultValidation.None) + .ExecuteBufferedAsync(Encoding.UTF8); + + if (idet.ExitCode != 0) + { + _logger.LogInformation( + "FFmpeg idet with arguments {Arguments} exited with code {ExitCode}", + arguments, + idet.ExitCode); + + return Option.None; + } + + var stats = new IdetStatistics(); + + var singleMatch = SingleFrameRegex().Match(idet.StandardOutput); + if (singleMatch.Success) + { + stats.SingleTff = int.Parse(singleMatch.Groups[1].Value, NumberFormatInfo.InvariantInfo); + stats.SingleBff = int.Parse(singleMatch.Groups[2].Value, NumberFormatInfo.InvariantInfo); + stats.SingleProgressive = int.Parse(singleMatch.Groups[3].Value, NumberFormatInfo.InvariantInfo); + } + + var multiMatch = MultiFrameRegex().Match(idet.StandardOutput); + if (multiMatch.Success) + { + stats.MultiTff = int.Parse(multiMatch.Groups[1].Value, NumberFormatInfo.InvariantInfo); + stats.MultiBff = int.Parse(multiMatch.Groups[2].Value, NumberFormatInfo.InvariantInfo); + stats.MultiProgressive = int.Parse(multiMatch.Groups[3].Value, NumberFormatInfo.InvariantInfo); + } + + return stats; + } + private async Task AnalyzeDuration(string ffmpegPath, string path, MediaVersion version) { try @@ -366,6 +460,7 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider version.Width = videoStream.width; version.Height = videoStream.height; version.VideoScanKind = ScanKindFromFieldOrder(videoStream.field_order); + version.InterlacedRatio = null; version.RFrameRate = videoStream.r_frame_rate; var stream = new MediaStream @@ -600,4 +695,27 @@ public class LocalStatisticsProvider : ILocalStatisticsProvider null); } // ReSharper restore InconsistentNaming + + [GeneratedRegex(@"\[SAR\s+([0-9]+:[0-9]+)\s+DAR\s+([0-9]+:[0-9]+)\]")] + private static partial Regex SarDarRegex(); + + [GeneratedRegex(@"Single frame detection: TFF: (\d+) BFF: (\d+) Progressive: (\d+)")] + private static partial Regex SingleFrameRegex(); + + [GeneratedRegex(@"Multi frame detection: TFF: (\d+) BFF: (\d+) Progressive: (\d+)")] + private static partial Regex MultiFrameRegex(); + + private class IdetStatistics + { + public int SingleTff { get; set; } + public int SingleBff { get; set; } + public int SingleProgressive { get; set; } + public int MultiTff { get; set; } + public int MultiBff { get; set; } + public int MultiProgressive { get; set; } + + public int TotalInterlacedFrames => SingleTff + SingleBff + MultiTff + MultiBff; + public int TotalProgressiveFrames => SingleProgressive + MultiProgressive; + public int TotalFrames => TotalInterlacedFrames + TotalProgressiveFrames; + } } diff --git a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs index 18127ca6c..5a5ba11f5 100644 --- a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs @@ -283,6 +283,8 @@ public class TranscodingTests graphicsElementLoader, MemoryCache, Substitute.For(), + Substitute.For(), + Substitute.For(), LoggerFactory.CreateLogger()); var songVideoGenerator = new SongVideoGenerator(tempFilePool, mockImageCache, service); @@ -375,7 +377,7 @@ public class TranscodingTests ExecutableName("ffprobe"), true, channel, - videoVersion, + new MediaItemVideoVersion(song, videoVersion), new MediaItemAudioVersion(song, songVersion), videoPath, file, @@ -695,7 +697,7 @@ public class TranscodingTests ExecutableName("ffprobe"), true, channel, - v, + new MediaItemVideoVersion(null, v), new MediaItemAudioVersion(null, v), file, file, @@ -990,6 +992,8 @@ public class TranscodingTests graphicsElementLoader, MemoryCache, Substitute.For(), + Substitute.For(), + Substitute.For(), LoggerFactory.CreateLogger()); return service; diff --git a/ErsatzTV/Pages/Settings/FFmpegSettings.razor b/ErsatzTV/Pages/Settings/FFmpegSettings.razor index 1c4c94455..45990d24b 100644 --- a/ErsatzTV/Pages/Settings/FFmpegSettings.razor +++ b/ErsatzTV/Pages/Settings/FFmpegSettings.razor @@ -68,6 +68,12 @@ + +
+ Probe For Interlaced Frames +
+ +
Save Troubleshooting Reports To Disk