repo creation with initial code after cloning public repo
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class ActiveRecordingInfo
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public TimerInfo Timer { get; set; }
|
||||
|
||||
public CancellationTokenSource CancellationTokenSource { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ChannelInfo.
|
||||
/// </summary>
|
||||
public class ChannelInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number.
|
||||
/// </summary>
|
||||
/// <value>The number.</value>
|
||||
public string Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Id.
|
||||
/// </summary>
|
||||
/// <value>The id of the channel.</value>
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public string TunerChannelId { get; set; }
|
||||
|
||||
public string CallSign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tuner host identifier.
|
||||
/// </summary>
|
||||
/// <value>The tuner host identifier.</value>
|
||||
public string TunerHostId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the channel.
|
||||
/// </summary>
|
||||
/// <value>The type of the channel.</value>
|
||||
public ChannelType ChannelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the group of the channel.
|
||||
/// </summary>
|
||||
/// <value>The group of the channel.</value>
|
||||
public string ChannelGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image path if it can be accessed directly from the file system.
|
||||
/// </summary>
|
||||
/// <value>The image path.</value>
|
||||
public string ImagePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image url if it can be downloaded.
|
||||
/// </summary>
|
||||
/// <value>The image URL.</value>
|
||||
public string ImageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has image.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [has image] contains no value, <c>true</c> if [has image]; otherwise, <c>false</c>.</value>
|
||||
public bool? HasImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is favorite.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is favorite] contains no value, <c>true</c> if [is favorite]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsFavorite { get; set; }
|
||||
|
||||
public bool? IsHD { get; set; }
|
||||
|
||||
public string AudioCodec { get; set; }
|
||||
|
||||
public string VideoCodec { get; set; }
|
||||
|
||||
public string[] Tags { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv;
|
||||
|
||||
/// <summary>
|
||||
/// Service responsible for managing the Live TV guide.
|
||||
/// </summary>
|
||||
public interface IGuideManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the guide information.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="GuideInfo"/>.</returns>
|
||||
GuideInfo GetGuideInfo();
|
||||
|
||||
/// <summary>
|
||||
/// Refresh the guide.
|
||||
/// </summary>
|
||||
/// <param name="progress">The <see cref="IProgress{T}"/> to use.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
|
||||
/// <returns>Task representing the refresh operation.</returns>
|
||||
Task RefreshGuide(IProgress<double> progress, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv;
|
||||
|
||||
/// <summary>
|
||||
/// Service responsible for managing <see cref="IListingsProvider"/>s and mapping
|
||||
/// their channels to channels provided by <see cref="ITunerHost"/>s.
|
||||
/// </summary>
|
||||
public interface IListingsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Saves the listing provider.
|
||||
/// </summary>
|
||||
/// <param name="info">The listing provider information.</param>
|
||||
/// <param name="validateLogin">A value indicating whether to validate login.</param>
|
||||
/// <param name="validateListings">A value indicating whether to validate listings..</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the listing provider.
|
||||
/// </summary>
|
||||
/// <param name="id">The listing provider's id.</param>
|
||||
void DeleteListingsProvider(string? id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lineups.
|
||||
/// </summary>
|
||||
/// <param name="providerType">Type of the provider.</param>
|
||||
/// <param name="providerId">The provider identifier.</param>
|
||||
/// <param name="country">The country.</param>
|
||||
/// <param name="location">The location.</param>
|
||||
/// <returns>The available lineups.</returns>
|
||||
Task<List<NameIdPair>> GetLineups(string? providerType, string? providerId, string? country, string? location);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the programs for a provided channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel to retrieve programs for.</param>
|
||||
/// <param name="startDateUtc">The earliest date to retrieve programs for.</param>
|
||||
/// <param name="endDateUtc">The latest date to retrieve programs for.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
|
||||
/// <returns>The available programs.</returns>
|
||||
Task<IEnumerable<ProgramInfo>> GetProgramsAsync(
|
||||
ChannelInfo channel,
|
||||
DateTime startDateUtc,
|
||||
DateTime endDateUtc,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Adds metadata from the <see cref="IListingsProvider"/>s to the provided channels.
|
||||
/// </summary>
|
||||
/// <param name="channels">The channels.</param>
|
||||
/// <param name="enableCache">A value indicating whether to use the EPG channel cache.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
|
||||
/// <returns>A task representing the metadata population.</returns>
|
||||
Task AddProviderMetadata(IList<ChannelInfo> channels, bool enableCache, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel mapping options for a provider.
|
||||
/// </summary>
|
||||
/// <param name="providerId">The id of the provider to use.</param>
|
||||
/// <returns>The channel mapping options.</returns>
|
||||
Task<ChannelMappingOptionsDto> GetChannelMappingOptions(string? providerId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the channel mapping.
|
||||
/// </summary>
|
||||
/// <param name="providerId">The id of the provider for the mapping.</param>
|
||||
/// <param name="tunerChannelNumber">The tuner channel number.</param>
|
||||
/// <param name="providerChannelNumber">The provider channel number.</param>
|
||||
/// <returns>The updated channel mapping.</returns>
|
||||
Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public interface IListingsProvider
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
string Type { get; }
|
||||
|
||||
Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
|
||||
|
||||
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||
|
||||
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
||||
|
||||
Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Events;
|
||||
using Jellyfin.Database.Implementations.Entities;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages all live tv services installed on the server.
|
||||
/// </summary>
|
||||
public interface ILiveTvManager
|
||||
{
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
||||
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the services.
|
||||
/// </summary>
|
||||
/// <value>The services.</value>
|
||||
IReadOnlyList<ILiveTvService> Services { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new timer defaults asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{TimerInfo}.</returns>
|
||||
Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new timer defaults.
|
||||
/// </summary>
|
||||
/// <param name="programId">The program identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{SeriesTimerInfoDto}.</returns>
|
||||
Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the timer.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CancelTimer(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the series timer.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CancelSeriesTimer(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timer.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{TimerInfoDto}.</returns>
|
||||
Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the series timer.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{TimerInfoDto}.</returns>
|
||||
Task<SeriesTimerInfoDto> GetSeriesTimer(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recordings.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>A recording.</returns>
|
||||
Task<QueryResult<BaseItemDto>> GetRecordingsAsync(RecordingQuery query, DtoOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timers.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{QueryResult{TimerInfoDto}}.</returns>
|
||||
Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the series timers.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{QueryResult{SeriesTimerInfoDto}}.</returns>
|
||||
Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the program.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>Task{ProgramInfoDto}.</returns>
|
||||
Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the programs.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IEnumerable{ProgramInfo}.</returns>
|
||||
Task<QueryResult<BaseItemDto>> GetPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the timer.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the timer.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the timer.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CreateTimer(TimerInfoDto timer, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the series timer.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recommended programs.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Recommended programs.</returns>
|
||||
Task<QueryResult<BaseItemDto>> GetRecommendedProgramsAsync(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recommended programs internal.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Recommended programs.</returns>
|
||||
QueryResult<BaseItem> GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the live tv information.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{LiveTvInfo}.</returns>
|
||||
LiveTvInfo GetLiveTvInfo(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the tuner.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ResetTuner(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the live tv folder.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Live TV folder.</returns>
|
||||
Folder GetInternalLiveTvFolder(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enabled users.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{User}.</returns>
|
||||
IEnumerable<User> GetEnabledUsers();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal channels.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="dtoOptions">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Internal channels.</returns>
|
||||
QueryResult<BaseItem> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the information to program dto.
|
||||
/// </summary>
|
||||
/// <param name="programs">The programs.</param>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem Item, BaseItemDto ItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the channel information.
|
||||
/// </summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
void AddChannelInfo(IReadOnlyCollection<(BaseItemDto ItemDto, LiveTvChannel Channel)> items, DtoOptions options, User user);
|
||||
|
||||
void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null);
|
||||
|
||||
Task<BaseItem[]> GetRecordingFoldersAsync(User user);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single live tv back end (next pvr, media portal, etc).
|
||||
/// </summary>
|
||||
public interface ILiveTvService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the home page URL.
|
||||
/// </summary>
|
||||
/// <value>The home page URL.</value>
|
||||
string HomePageUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channels async.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{ChannelInfo}}.</returns>
|
||||
Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="timerId">The timer identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CancelTimerAsync(string timerId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the series timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="timerId">The timer identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the series timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="updatedTimer">The updated timer information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the series timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recordings asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
|
||||
Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new timer defaults asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="program">The program.</param>
|
||||
/// <returns>Task{SeriesTimerInfo}.</returns>
|
||||
Task<SeriesTimerInfo> GetNewTimerDefaultsAsync(CancellationToken cancellationToken, ProgramInfo program = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the series timers asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{SeriesTimerInfo}}.</returns>
|
||||
Task<IEnumerable<SeriesTimerInfo>> GetSeriesTimersAsync(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the programs asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="startDateUtc">The start date UTC.</param>
|
||||
/// <param name="endDateUtc">The end date UTC.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{ProgramInfo}}.</returns>
|
||||
Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel stream.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="streamId">The stream identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel stream media sources.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
||||
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Closes the live stream.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CloseLiveStream(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the tuner.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ResetTuner(string id, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface ISupportsNewTimerIds
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the series timer asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface ISupportsDirectStreamProvider
|
||||
{
|
||||
Task<ILiveStream> GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv;
|
||||
|
||||
/// <summary>
|
||||
/// Service responsible for managing LiveTV recordings.
|
||||
/// </summary>
|
||||
public interface IRecordingsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the path for the provided timer id.
|
||||
/// </summary>
|
||||
/// <param name="id">The timer id.</param>
|
||||
/// <returns>The recording path, or <c>null</c> if none exists.</returns>
|
||||
string? GetActiveRecordingPath(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information for an active recording.
|
||||
/// </summary>
|
||||
/// <param name="path">The recording path.</param>
|
||||
/// <returns>The <see cref="ActiveRecordingInfo"/>, or <c>null</c> if none exists.</returns>
|
||||
ActiveRecordingInfo? GetActiveRecordingInfo(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recording folders.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="VirtualFolderInfo"/> for each recording folder.</returns>
|
||||
IEnumerable<VirtualFolderInfo> GetRecordingFolders();
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the recording folders all exist, and removes unused folders.
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
Task CreateRecordingFolders();
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the recording with the provided timer id, if one is active.
|
||||
/// </summary>
|
||||
/// <param name="timerId">The timer id.</param>
|
||||
/// <param name="timer">The timer.</param>
|
||||
void CancelRecording(string timerId, TimerInfo? timer);
|
||||
|
||||
/// <summary>
|
||||
/// Records a stream.
|
||||
/// </summary>
|
||||
/// <param name="recordingInfo">The recording info.</param>
|
||||
/// <param name="channel">The channel associated with the recording timer.</param>
|
||||
/// <param name="recordingEndDate">The time to stop recording.</param>
|
||||
/// <returns>Task representing the recording process.</returns>
|
||||
Task RecordStream(ActiveRecordingInfo recordingInfo, BaseItem channel, DateTime recordingEndDate);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public interface ITunerHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
string Type { get; }
|
||||
|
||||
bool IsSupported { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channels.
|
||||
/// </summary>
|
||||
/// <param name="enableCache">Option to enable using cache.</param>
|
||||
/// <param name="cancellationToken">The CancellationToken for this operation.</param>
|
||||
/// <returns>Task<IEnumerable<ChannelInfo>>.</returns>
|
||||
Task<List<ChannelInfo>> GetChannels(bool enableCache, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel stream.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="streamId">The stream identifier.</param>
|
||||
/// <param name="currentLiveStreams">The current live streams.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||
/// <returns>Live stream wrapped in a task.</returns>
|
||||
Task<ILiveStream> GetChannelStream(string channelId, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel stream media sources.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
||||
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||
|
||||
Task<List<TunerHostInfo>> DiscoverDevices(int discoveryDurationMs, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IConfigurableTunerHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates the specified information.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task Validate(TunerHostInfo info);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv;
|
||||
|
||||
/// <summary>
|
||||
/// Service responsible for managing the <see cref="ITunerHost"/>s.
|
||||
/// </summary>
|
||||
public interface ITunerHostManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="ITunerHost"/>s.
|
||||
/// </summary>
|
||||
IReadOnlyList<ITunerHost> TunerHosts { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="NameIdPair"/>s for the available <see cref="ITunerHost"/>s.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="NameIdPair"/>s.</returns>
|
||||
IEnumerable<NameIdPair> GetTunerHostTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Saves the tuner host.
|
||||
/// </summary>
|
||||
/// <param name="info">Turner host to save.</param>
|
||||
/// <param name="dataSourceChanged">Option to specify that data source has changed.</param>
|
||||
/// <returns>Tuner host information wrapped in a task.</returns>
|
||||
Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true);
|
||||
|
||||
/// <summary>
|
||||
/// Discovers the available tuners.
|
||||
/// </summary>
|
||||
/// <param name="newDevicesOnly">A value indicating whether to only return new devices.</param>
|
||||
/// <returns>The <see cref="TunerHostInfo"/>s.</returns>
|
||||
IAsyncEnumerable<TunerHostInfo> DiscoverTuners(bool newDevicesOnly);
|
||||
|
||||
/// <summary>
|
||||
/// Scans for tuner devices that have changed URLs.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
|
||||
/// <returns>A task that represents the scanning operation.</returns>
|
||||
Task ScanForTunerDeviceChanges(CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class LiveTvChannel : BaseItem, IHasMediaSources, IHasProgramAttributes
|
||||
{
|
||||
[JsonIgnore]
|
||||
public override bool SupportsPositionTicksResume => false;
|
||||
|
||||
[JsonIgnore]
|
||||
public override SourceType SourceType => SourceType.LiveTV;
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool EnableRememberingTrackSelections => false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number.
|
||||
/// </summary>
|
||||
/// <value>The number.</value>
|
||||
public string Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the channel.
|
||||
/// </summary>
|
||||
/// <value>The type of the channel.</value>
|
||||
public ChannelType ChannelType { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public override LocationType LocationType => LocationType.Remote;
|
||||
|
||||
[JsonIgnore]
|
||||
public override MediaType MediaType => ChannelType == ChannelType.Radio ? MediaType.Audio : MediaType.Video;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsSports { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is series.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is series; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is news.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsNews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsRepeat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode title.
|
||||
/// </summary>
|
||||
/// <value>The episode title.</value>
|
||||
[JsonIgnore]
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName)
|
||||
{
|
||||
list.Insert(0, GetClientTypeName() + "-" + Name);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.LiveTvChannel;
|
||||
}
|
||||
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
if (double.TryParse(Number, CultureInfo.InvariantCulture, out double number))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty);
|
||||
}
|
||||
|
||||
return (Number ?? string.Empty) + "-" + (Name ?? string.Empty);
|
||||
}
|
||||
|
||||
public override string GetClientTypeName()
|
||||
{
|
||||
return "TvChannel";
|
||||
}
|
||||
|
||||
public IEnumerable<BaseItem> GetTaggedItems() => [];
|
||||
|
||||
public override IReadOnlyList<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
var info = new MediaSourceInfo
|
||||
{
|
||||
Id = Id.ToString("N", CultureInfo.InvariantCulture),
|
||||
Protocol = PathProtocol ?? MediaProtocol.File,
|
||||
MediaStreams = Array.Empty<MediaStream>(),
|
||||
Name = Name,
|
||||
Path = Path,
|
||||
RunTimeTicks = RunTimeTicks,
|
||||
Type = MediaSourceType.Placeholder,
|
||||
IsInfiniteStream = RunTimeTicks is null
|
||||
};
|
||||
|
||||
return [info];
|
||||
}
|
||||
|
||||
public override IReadOnlyList<MediaStream> GetMediaStreams()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture), "metadata");
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
/// <summary>
|
||||
/// Class LiveTvConflictException.
|
||||
/// </summary>
|
||||
public class LiveTvConflictException : Exception
|
||||
{
|
||||
public LiveTvConflictException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591, SA1306
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.Providers;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
[Common.RequiresSourceSerialisation]
|
||||
public class LiveTvProgram : BaseItem, IHasLookupInfo<ItemLookupInfo>, IHasStartDate, IHasProgramAttributes
|
||||
{
|
||||
private const string EmbyServiceName = "Emby";
|
||||
|
||||
public LiveTvProgram()
|
||||
{
|
||||
IsVirtualItem = true;
|
||||
}
|
||||
|
||||
public string SeriesName { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public override SourceType SourceType => SourceType.LiveTV;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets start date of the program, in UTC.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is repeat.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsRepeat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode title.
|
||||
/// </summary>
|
||||
/// <value>The episode title.</value>
|
||||
[JsonIgnore]
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string ShowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is movie.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is movie; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsSports => Tags.Contains("Sports", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is series.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is series; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is live.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsLive => Tags.Contains("Live", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is news.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsNews => Tags.Contains("News", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is premiere.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is premiere; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsPremiere => Tags.Contains("Premiere", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself.
|
||||
/// </summary>
|
||||
/// <value>The containing folder path.</value>
|
||||
[JsonIgnore]
|
||||
public override string ContainingFolderPath => Path;
|
||||
|
||||
// [JsonIgnore]
|
||||
// public override string MediaType
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
|
||||
// }
|
||||
// }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsAiring
|
||||
{
|
||||
get
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
return now >= StartDate && now < EndDate;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasAired
|
||||
{
|
||||
get
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
return now >= EndDate;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
// Optimization
|
||||
if (IsNews || IsSports)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.SupportsPeople;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool SupportsAncestors => false;
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
if (!IsSeries)
|
||||
{
|
||||
var key = this.GetProviderId(MetadataProvider.Imdb);
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
list.Insert(0, key);
|
||||
}
|
||||
|
||||
key = this.GetProviderId(MetadataProvider.Tmdb);
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
list.Insert(0, key);
|
||||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(EpisodeTitle))
|
||||
{
|
||||
var name = GetClientTypeName();
|
||||
|
||||
list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
var serviceName = ServiceName;
|
||||
|
||||
if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 2.0 / 3;
|
||||
}
|
||||
|
||||
return 16.0 / 9;
|
||||
}
|
||||
|
||||
public override string GetClientTypeName()
|
||||
{
|
||||
return "Program";
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.LiveTvProgram;
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private LiveTvOptions GetConfiguration()
|
||||
{
|
||||
return ConfigurationManager.GetConfiguration<LiveTvOptions>("livetv");
|
||||
}
|
||||
|
||||
private ListingsProviderInfo GetListingsProviderInfo()
|
||||
{
|
||||
if (string.Equals(ServiceName, "Emby", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var config = GetConfiguration();
|
||||
|
||||
return config.ListingProviders.FirstOrDefault(i => !string.IsNullOrEmpty(i.MoviePrefix));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override string GetNameForMetadataLookup()
|
||||
{
|
||||
var name = base.GetNameForMetadataLookup();
|
||||
|
||||
var listings = GetListingsProviderInfo();
|
||||
|
||||
if (listings is not null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(listings.MoviePrefix) && name.StartsWith(listings.MoviePrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
name = name.Substring(listings.MoviePrefix.Length).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class ProgramInfo
|
||||
{
|
||||
public ProgramInfo()
|
||||
{
|
||||
Genres = new List<string>();
|
||||
|
||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id of the program.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel identifier.
|
||||
/// </summary>
|
||||
/// <value>The channel identifier.</value>
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the program.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the official rating.
|
||||
/// </summary>
|
||||
/// <value>The official rating.</value>
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the overview.
|
||||
/// </summary>
|
||||
/// <value>The overview.</value>
|
||||
public string Overview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the short overview.
|
||||
/// </summary>
|
||||
/// <value>The short overview.</value>
|
||||
public string ShortOverview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start date of the program, in UTC.
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the end date of the program, in UTC.
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the genre of the program.
|
||||
/// </summary>
|
||||
public List<string> Genres { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the original air date.
|
||||
/// </summary>
|
||||
/// <value>The original air date.</value>
|
||||
public DateTime? OriginalAirDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is hd.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value>
|
||||
public bool? IsHD { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is 3d.
|
||||
/// </summary>
|
||||
public bool? Is3D { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the audio.
|
||||
/// </summary>
|
||||
/// <value>The audio.</value>
|
||||
public ProgramAudio? Audio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating.
|
||||
/// </summary>
|
||||
/// <value>The community rating.</value>
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is repeat.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||
public bool IsRepeat { get; set; }
|
||||
|
||||
public bool IsSubjectToBlackout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode title.
|
||||
/// </summary>
|
||||
/// <value>The episode title.</value>
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image path if it can be accessed directly from the file system.
|
||||
/// </summary>
|
||||
/// <value>The image path.</value>
|
||||
public string ImagePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image url if it can be downloaded.
|
||||
/// </summary>
|
||||
/// <value>The image URL.</value>
|
||||
public string ImageUrl { get; set; }
|
||||
|
||||
public string ThumbImageUrl { get; set; }
|
||||
|
||||
public string LogoImageUrl { get; set; }
|
||||
|
||||
public string BackdropImageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has image.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [has image] contains no value, <c>true</c> if [has image]; otherwise, <c>false</c>.</value>
|
||||
public bool? HasImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is movie.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is movie; otherwise, <c>false</c>.</value>
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
|
||||
public bool IsSports { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is series.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is series; otherwise, <c>false</c>.</value>
|
||||
public bool IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is live.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value>
|
||||
public bool IsLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is news.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value>
|
||||
public bool IsNews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
|
||||
public bool IsKids { get; set; }
|
||||
|
||||
public bool IsEducational { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is premiere.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is premiere; otherwise, <c>false</c>.</value>
|
||||
public bool IsPremiere { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the production year.
|
||||
/// </summary>
|
||||
/// <value>The production year.</value>
|
||||
public int? ProductionYear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the home page URL.
|
||||
/// </summary>
|
||||
/// <value>The home page URL.</value>
|
||||
public string HomePageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the series identifier.
|
||||
/// </summary>
|
||||
/// <value>The series identifier.</value>
|
||||
public string SeriesId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the show identifier.
|
||||
/// </summary>
|
||||
/// <value>The show identifier.</value>
|
||||
public string ShowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the season number.
|
||||
/// </summary>
|
||||
/// <value>The season number.</value>
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode number.
|
||||
/// </summary>
|
||||
/// <value>The episode number.</value>
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the etag.
|
||||
/// </summary>
|
||||
/// <value>The etag.</value>
|
||||
public string Etag { get; set; }
|
||||
|
||||
public Dictionary<string, string> ProviderIds { get; set; }
|
||||
|
||||
public Dictionary<string, string> SeriesProviderIds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class SeriesTimerInfo
|
||||
{
|
||||
public SeriesTimerInfo()
|
||||
{
|
||||
Days = new List<DayOfWeek>();
|
||||
SkipEpisodesInLibrary = true;
|
||||
KeepUntil = KeepUntil.UntilDeleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id of the recording.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channelId of the recording.
|
||||
/// </summary>
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the program identifier.
|
||||
/// </summary>
|
||||
/// <value>The program identifier.</value>
|
||||
public string ProgramId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the recording.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the service name.
|
||||
/// </summary>
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of the recording.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start date of the recording, in UTC.
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the end date of the recording, in UTC.
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [record any time].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [record any time]; otherwise, <c>false</c>.</value>
|
||||
public bool RecordAnyTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [record any channel].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [record any channel]; otherwise, <c>false</c>.</value>
|
||||
public bool RecordAnyChannel { get; set; }
|
||||
|
||||
public int KeepUpTo { get; set; }
|
||||
|
||||
public KeepUntil KeepUntil { get; set; }
|
||||
|
||||
public bool SkipEpisodesInLibrary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [record new only].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [record new only]; otherwise, <c>false</c>.</value>
|
||||
public bool RecordNewOnly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the days.
|
||||
/// </summary>
|
||||
/// <value>The days.</value>
|
||||
public List<DayOfWeek> Days { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the priority.
|
||||
/// </summary>
|
||||
/// <value>The priority.</value>
|
||||
public int Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pre padding seconds.
|
||||
/// </summary>
|
||||
/// <value>The pre padding seconds.</value>
|
||||
public int PrePaddingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the post padding seconds.
|
||||
/// </summary>
|
||||
/// <value>The post padding seconds.</value>
|
||||
public int PostPaddingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is pre padding required.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is pre padding required; otherwise, <c>false</c>.</value>
|
||||
public bool IsPrePaddingRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is post padding required.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
|
||||
public bool IsPostPaddingRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the series identifier.
|
||||
/// </summary>
|
||||
/// <value>The series identifier.</value>
|
||||
public string SeriesId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class TimerEventInfo
|
||||
{
|
||||
public TimerEventInfo(string id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public string Id { get; }
|
||||
|
||||
public Guid? ProgramId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class TimerInfo
|
||||
{
|
||||
public TimerInfo()
|
||||
{
|
||||
Genres = Array.Empty<string>();
|
||||
KeepUntil = KeepUntil.UntilDeleted;
|
||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
Tags = Array.Empty<string>();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> ProviderIds { get; set; }
|
||||
|
||||
public Dictionary<string, string> SeriesProviderIds { get; set; }
|
||||
|
||||
public string[] Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id of the recording.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the series timer identifier.
|
||||
/// </summary>
|
||||
public string SeriesTimerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channelId of the recording.
|
||||
/// </summary>
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the program identifier.
|
||||
/// </summary>
|
||||
/// <value>The program identifier.</value>
|
||||
public string ProgramId { get; set; }
|
||||
|
||||
public string ShowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the recording.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of the recording.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
public string SeriesId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start date of the recording, in UTC.
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the end date of the recording, in UTC.
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status.
|
||||
/// </summary>
|
||||
/// <value>The status.</value>
|
||||
public RecordingStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pre padding seconds.
|
||||
/// </summary>
|
||||
/// <value>The pre padding seconds.</value>
|
||||
public int PrePaddingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the post padding seconds.
|
||||
/// </summary>
|
||||
/// <value>The post padding seconds.</value>
|
||||
public int PostPaddingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is pre padding required.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is pre padding required; otherwise, <c>false</c>.</value>
|
||||
public bool IsPrePaddingRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is post padding required.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
|
||||
public bool IsPostPaddingRequired { get; set; }
|
||||
|
||||
public bool IsManual { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the priority.
|
||||
/// </summary>
|
||||
/// <value>The priority.</value>
|
||||
public int Priority { get; set; }
|
||||
|
||||
public int RetryCount { get; set; }
|
||||
|
||||
// Program properties
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode number.
|
||||
/// </summary>
|
||||
/// <value>The episode number.</value>
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public bool IsSports => Tags.Contains("Sports", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public bool IsNews => Tags.Contains("News", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public bool IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is live.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value>
|
||||
[JsonIgnore]
|
||||
public bool IsLive => Tags.Contains("Live", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsPremiere => Tags.Contains("Premiere", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public int? ProductionYear { get; set; }
|
||||
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
public DateTime? OriginalAirDate { get; set; }
|
||||
|
||||
public bool IsProgramSeries { get; set; }
|
||||
|
||||
public bool IsRepeat { get; set; }
|
||||
|
||||
public string HomePageUrl { get; set; }
|
||||
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
public string[] Genres { get; set; }
|
||||
|
||||
public string RecordingPath { get; set; }
|
||||
|
||||
public KeepUntil KeepUntil { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user