diff --git a/Kyoo.Common/Models/Chapter.cs b/Kyoo.Common/Models/Chapter.cs new file mode 100644 index 00000000..51ccc231 --- /dev/null +++ b/Kyoo.Common/Models/Chapter.cs @@ -0,0 +1,38 @@ +namespace Kyoo.Models +{ + /// + /// A chapter to split an episode in multiple parts. + /// + public class Chapter + { + /// + /// The start time of the chapter (in second from the start of the episode). + /// + public float StartTime { get; set; } + + /// + /// The end time of the chapter (in second from the start of the episode)&. + /// + public float EndTime { get; set; } + + /// + /// The name of this chapter. This should be a human-readable name that could be presented to the user. + /// There should be well-known chapters name for commonly used chapters. + /// For example, use "Opening" for the introduction-song and "Credits" for the end chapter with credits. + /// + public string Name { get; set; } + + /// + /// Create a new . + /// + /// The start time of the chapter (in second) + /// The end time of the chapter (in second) + /// The name of this chapter + public Chapter(float startTime, float endTime, string name) + { + StartTime = startTime; + EndTime = endTime; + Name = name; + } + } +} \ No newline at end of file diff --git a/Kyoo.Common/Models/WatchItem.cs b/Kyoo.Common/Models/WatchItem.cs index 71ec1993..a7e15fd1 100644 --- a/Kyoo.Common/Models/WatchItem.cs +++ b/Kyoo.Common/Models/WatchItem.cs @@ -9,95 +9,137 @@ using PathIO = System.IO.Path; namespace Kyoo.Models { - public class Chapter - { - public float StartTime; - public float EndTime; - public string Name; - - public Chapter(float startTime, float endTime, string name) - { - StartTime = startTime; - EndTime = endTime; - Name = name; - } - } - + /// + /// A watch item give information useful for playback. + /// Information about tracks and display information that could be used by the player. + /// This contains mostly data from an with another form. + /// public class WatchItem { + /// + /// The ID of the episode associated with this item. + /// public int EpisodeID { get; set; } - - public string ShowTitle { get; set; } - public string ShowSlug { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } - public int AbsoluteNumber { get; set; } - public string Title { get; set; } + + /// + /// The slug of this episode. + /// public string Slug { get; set; } + + /// + /// The title of the show containing this episode. + /// + public string ShowTitle { get; set; } + + /// + /// The slug of the show containing this episode + /// + public string ShowSlug { get; set; } + + /// + /// The season in witch this episode is in. This defaults to -1 if not specified. + /// + public int SeasonNumber { get; set; } + + /// + /// The number of this episode is it's season. This defaults to -1 if not specified. + /// + public int EpisodeNumber { get; set; } + + /// + /// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season. + /// This defaults to -1 if not specified. + /// + public int AbsoluteNumber { get; set; } + + /// + /// The title of this episode. + /// + public string Title { get; set; } + + /// + /// The release date of this episode. It can be null if unknown. + /// public DateTime? ReleaseDate { get; set; } + + /// + /// The path of the video file for this episode. Any format supported by a is allowed. + /// [SerializeIgnore] public string Path { get; set; } + + /// + /// The episode that come before this one if you follow usual watch orders. + /// If this is the first episode or this is a movie, it will be null. + /// public Episode PreviousEpisode { get; set; } + + /// + /// The episode that come after this one if you follow usual watch orders. + /// If this is the last aired episode or this is a movie, it will be null. + /// public Episode NextEpisode { get; set; } + + /// + /// true if this is a movie, false otherwise. + /// public bool IsMovie { get; set; } + /// + /// The path of this item's poster. + /// By default, the http path for the poster is returned from the public API. + /// This can be disabled using the internal query flag. + /// [SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; } + + /// + /// The path of this item's logo. + /// By default, the http path for the logo is returned from the public API. + /// This can be disabled using the internal query flag. + /// [SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; } + + /// + /// The path of this item's backdrop. + /// By default, the http path for the backdrop is returned from the public API. + /// This can be disabled using the internal query flag. + /// [SerializeAs("{HOST}/api/show/{ShowSlug}/backdrop")] public string Backdrop { get; set; } + /// + /// The container of the video file of this episode. + /// Common containers are mp4, mkv, avi and so on. + /// public string Container { get; set; } + + /// + /// The video track. See for more information. + /// public Track Video { get; set; } + + /// + /// The list of audio tracks. See for more information. + /// public ICollection Audios { get; set; } + + /// + /// The list of subtitles tracks. See for more information. + /// public ICollection Subtitles { get; set; } + + /// + /// The list of chapters. See for more information. + /// public ICollection Chapters { get; set; } + - public WatchItem() { } - - private WatchItem(int episodeID, - Show show, - int seasonNumber, - int episodeNumber, - int absoluteNumber, - string title, - DateTime? releaseDate, - string path) - { - EpisodeID = episodeID; - ShowTitle = show.Title; - ShowSlug = show.Slug; - SeasonNumber = seasonNumber; - EpisodeNumber = episodeNumber; - AbsoluteNumber = absoluteNumber; - Title = title; - ReleaseDate = releaseDate; - Path = path; - IsMovie = show.IsMovie; - - Poster = show.Poster; - Logo = show.Logo; - Backdrop = show.Backdrop; - - Container = Path.Substring(Path.LastIndexOf('.') + 1); - Slug = Episode.GetSlug(ShowSlug, seasonNumber, episodeNumber, absoluteNumber); - } - - private WatchItem(int episodeID, - Show show, - int seasonNumber, - int episodeNumber, - int absoluteNumber, - string title, - DateTime? releaseDate, - string path, - Track video, - ICollection audios, - ICollection subtitles) - : this(episodeID, show, seasonNumber, episodeNumber, absoluteNumber, title, releaseDate, path) - { - Video = video; - Audios = audios; - Subtitles = subtitles; - } - + /// + /// Create a from an . + /// + /// The episode to transform. + /// + /// A library manager to retrieve the next and previous episode and load the show & tracks of the episode. + /// + /// A new WatchItem representing the given episode. public static async Task FromEpisode(Episode ep, ILibraryManager library) { Episode previous = null; @@ -123,24 +165,27 @@ namespace Kyoo.Models next = await library.GetOrDefault(ep.ShowID, ep.SeasonNumber, ep.EpisodeNumber + 1); } - return new WatchItem(ep.ID, - ep.Show, - ep.SeasonNumber, - ep.EpisodeNumber, - ep.AbsoluteNumber, - ep.Title, - ep.ReleaseDate, - ep.Path, - ep.Tracks.FirstOrDefault(x => x.Type == StreamType.Video), - ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(), - ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray()) + return new WatchItem { + EpisodeID = ep.ID, + ShowSlug = ep.Show.Slug, + SeasonNumber = ep.SeasonNumber, + EpisodeNumber = ep.EpisodeNumber, + AbsoluteNumber = ep.AbsoluteNumber, + Title = ep.Title, + ReleaseDate = ep.ReleaseDate, + Path = ep.Path, + Video = ep.Tracks.FirstOrDefault(x => x.Type == StreamType.Video), + Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(), + Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(), PreviousEpisode = previous, NextEpisode = next, Chapters = await GetChapters(ep.Path) }; } + // TODO move this method in a controller to support abstraction. + // TODO use a IFileManager to retrieve and read files. private static async Task> GetChapters(string episodePath) { string path = PathIO.Combine(