diff --git a/CHANGELOG.md b/CHANGELOG.md
index d85de6688..3f4c9d6b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix artwork upload on Windows
+- Fix unicode song metadata on Windows
+- Fix unicode console output on Windows
+- Fix TV Show NFO metadata processing when `year` is missing
### Changed
- Use custom log database backend which should be more portable (i.e. work in osx-arm64)
diff --git a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs
index 6b51b0847..8a4e55958 100644
--- a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs
+++ b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs
@@ -969,9 +969,9 @@ namespace ErsatzTV.Core.Metadata
}
}
- private static int? GetYear(int year, string premiered)
+ private static int? GetYear(int? year, string premiered)
{
- if (year > 1000)
+ if (year is > 1000)
{
return year;
}
@@ -989,9 +989,9 @@ namespace ErsatzTV.Core.Metadata
return null;
}
- private static DateTime? GetAired(int year, string aired)
+ private static DateTime? GetAired(int? year, string aired)
{
- DateTime? fallback = year > 1000 ? new DateTime(year, 1, 1) : null;
+ DateTime? fallback = year is > 1000 ? new DateTime(year.Value, 1, 1) : null;
if (string.IsNullOrWhiteSpace(aired))
{
diff --git a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs
index a6aa8098e..5cb9084fd 100644
--- a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs
+++ b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
+using System.Text;
using System.Threading.Tasks;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Extensions;
@@ -141,7 +142,9 @@ namespace ErsatzTV.Core.Metadata
FileName = ffprobePath,
RedirectStandardOutput = true,
RedirectStandardError = true,
- UseShellExecute = false
+ UseShellExecute = false,
+ StandardOutputEncoding = Encoding.UTF8,
+ StandardErrorEncoding = Encoding.UTF8
};
startInfo.ArgumentList.Add("-v");
diff --git a/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs b/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs
index 8224232c4..835338a55 100644
--- a/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs
+++ b/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs
@@ -9,8 +9,15 @@ namespace ErsatzTV.Core.Metadata.Nfo
[XmlElement("title")]
public string Title { get; set; }
+ [XmlIgnore]
+ public int? Year { get; set; }
+
[XmlElement("year")]
- public int Year { get; set; }
+ public string YearAsText
+ {
+ get => Year.HasValue ? Year.ToString() : null;
+ set => Year = !string.IsNullOrWhiteSpace(value) ? int.Parse(value) : default(int?);
+ }
[XmlElement("plot")]
public string Plot { get; set; }
diff --git a/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs
new file mode 100644
index 000000000..7dc22725b
--- /dev/null
+++ b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs
@@ -0,0 +1,3843 @@
+//
+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.Migrations
+{
+ [DbContext(typeof(TvContext))]
+ [Migration("20211201191945_Reset_SongMetadataOnWindows")]
+ partial class Reset_SongMetadataOnWindows
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
+
+ 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("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("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("MovieMetadataId");
+
+ b.HasIndex("MusicVideoMetadataId");
+
+ b.HasIndex("OtherVideoMetadataId");
+
+ 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("ChannelId")
+ .HasColumnType("INTEGER");
+
+ b.Property("DateAdded")
+ .HasColumnType("TEXT");
+
+ b.Property("DateUpdated")
+ .HasColumnType("TEXT");
+
+ b.Property("EpisodeMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("MovieMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("MusicVideoMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("OtherVideoMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Path")
+ .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("ChannelId");
+
+ b.HasIndex("EpisodeMetadataId");
+
+ b.HasIndex("MovieMetadataId");
+
+ b.HasIndex("MusicVideoMetadataId");
+
+ b.HasIndex("OtherVideoMetadataId");
+
+ b.HasIndex("SeasonMetadataId");
+
+ b.HasIndex("ShowMetadataId");
+
+ b.HasIndex("SongMetadataId");
+
+ b.ToTable("Artwork", (string)null);
+ });
+
+ modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("FFmpegProfileId")
+ .HasColumnType("INTEGER");
+
+ b.Property("FallbackFillerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("Number")
+ .HasColumnType("TEXT");
+
+ b.Property("PreferredLanguageCode")
+ .HasColumnType("TEXT");
+
+ b.Property("StreamingMode")
+ .HasColumnType("INTEGER");
+
+ b.Property("UniqueId")
+ .HasColumnType("TEXT");
+
+ b.Property("WatermarkId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("FFmpegProfileId");
+
+ b.HasIndex("FallbackFillerId");
+
+ 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("INTEGER");
+
+ 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("Size")
+ .HasColumnType("INTEGER");
+
+ b.Property("VerticalMarginPercent")
+ .HasColumnType("INTEGER");
+
+ b.Property("WidthPercent")
+ .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.Director", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("EpisodeMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("MovieMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EpisodeMetadataId");
+
+ b.HasIndex("MovieMetadataId");
+
+ b.ToTable("Director", (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("AudioBitrate")
+ .HasColumnType("INTEGER");
+
+ b.Property("AudioBufferSize")
+ .HasColumnType("INTEGER");
+
+ b.Property("AudioChannels")
+ .HasColumnType("INTEGER");
+
+ b.Property("AudioCodec")
+ .HasColumnType("TEXT");
+
+ b.Property("AudioSampleRate")
+ .HasColumnType("INTEGER");
+
+ b.Property("HardwareAcceleration")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizeAudio")
+ .HasColumnType("INTEGER");
+
+ b.Property("NormalizeLoudness")
+ .HasColumnType("INTEGER");
+
+ b.Property("NormalizeVideo")
+ .HasColumnType("INTEGER");
+
+ b.Property("ResolutionId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ThreadCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Transcode")
+ .HasColumnType("INTEGER");
+
+ b.Property("VaapiDevice")
+ .HasColumnType("TEXT");
+
+ b.Property("VaapiDriver")
+ .HasColumnType("INTEGER");
+
+ b.Property("VideoBitrate")
+ .HasColumnType("INTEGER");
+
+ b.Property("VideoBufferSize")
+ .HasColumnType("INTEGER");
+
+ b.Property("VideoCodec")
+ .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("CollectionId")
+ .HasColumnType("INTEGER");
+
+ b.Property("CollectionType")
+ .HasColumnType("INTEGER");
+
+ b.Property("Count")
+ .HasColumnType("INTEGER");
+
+ b.Property("Duration")
+ .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("SmartCollectionId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CollectionId");
+
+ b.HasIndex("MediaItemId");
+
+ b.HasIndex("MultiCollectionId");
+
+ 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("MovieMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("MusicVideoMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("OtherVideoMetadataId")
+ .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("MovieMetadataId");
+
+ b.HasIndex("MusicVideoMetadataId");
+
+ b.HasIndex("OtherVideoMetadataId");
+
+ b.HasIndex("SeasonMetadataId");
+
+ b.HasIndex("ShowMetadataId");
+
+ b.HasIndex("SongMetadataId");
+
+ b.ToTable("Genre");
+ });
+
+ 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);
+ });
+
+ 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("Path")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryPathId");
+
+ 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("MediaVersionId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Path")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MediaVersionId");
+
+ b.HasIndex("Path")
+ .IsUnique();
+
+ b.ToTable("MediaFile", (string)null);
+ });
+
+ modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("LibraryPathId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryPathId");
+
+ b.ToTable("MediaItem", (string)null);
+ });
+
+ modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("MediaSource", (string)null);
+ });
+
+ 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("Default")
+ .HasColumnType("INTEGER");
+
+ 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("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("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("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("MovieId");
+
+ b.HasIndex("MusicVideoId");
+
+ b.HasIndex("OtherVideoId");
+
+ 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("MovieMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("MusicVideoMetadataId")
+ .HasColumnType("INTEGER");
+
+ b.Property("OtherVideoMetadataId")
+ .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("MovieMetadataId");
+
+ b.HasIndex("MusicVideoMetadataId");
+
+ b.HasIndex("OtherVideoMetadataId");
+
+ 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.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("Year")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MusicVideoId");
+
+ b.ToTable("MusicVideoMetadata", (string)null);
+ });
+
+ modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b =>
+ {
+ b.Property