update live tv database
This commit is contained in:
parent
68e64feafd
commit
f2abd8ba39
|
@ -340,7 +340,7 @@ namespace MediaBrowser.Api
|
|||
// We can really reduce the timeout for apps that are using the newer api
|
||||
if (!string.IsNullOrWhiteSpace(job.PlaySessionId))
|
||||
{
|
||||
timerDuration = 60000;
|
||||
timerDuration = 120000;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -879,7 +879,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
if (!EnableSplitTranscoding(state))
|
||||
{
|
||||
args += " -copyts";
|
||||
//args += " -copyts";
|
||||
}
|
||||
|
||||
return args;
|
||||
|
@ -910,11 +910,11 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
//toTimeParam = " -to " + MediaEncoder.GetTimeParameter(endTime);
|
||||
toTimeParam = " -t " + MediaEncoder.GetTimeParameter(TimeSpan.FromSeconds(durationSeconds).Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.IsOutputVideo && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
||||
{
|
||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
if (state.IsOutputVideo && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
||||
{
|
||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
||||
|
@ -959,6 +959,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
private bool EnableSplitTranscoding(StreamState state)
|
||||
{
|
||||
return false;
|
||||
if (string.Equals(Request.QueryString["EnableSplitTranscoding"], "false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -42,7 +42,14 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
var options = GetOptions();
|
||||
|
||||
if (options.EnableThrottling && IsThrottleAllowed(_job, options.ThrottleThresholdInSeconds))
|
||||
var threshold = options.ThrottleThresholdInSeconds;
|
||||
|
||||
if (!options.EnableThrottling)
|
||||
{
|
||||
threshold *= 2;
|
||||
}
|
||||
|
||||
if (IsThrottleAllowed(_job, threshold))
|
||||
{
|
||||
PauseTranscoding();
|
||||
}
|
||||
|
@ -56,7 +63,7 @@ namespace MediaBrowser.Api.Playback
|
|||
{
|
||||
if (!_isPaused)
|
||||
{
|
||||
_logger.Debug("Sending pause command to ffmpeg");
|
||||
//_logger.Debug("Sending pause command to ffmpeg");
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -74,7 +81,7 @@ namespace MediaBrowser.Api.Playback
|
|||
{
|
||||
if (_isPaused)
|
||||
{
|
||||
_logger.Debug("Sending unpause command to ffmpeg");
|
||||
//_logger.Debug("Sending unpause command to ffmpeg");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.Channels
|
|||
{
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
public string ChannelId { get; set; }
|
||||
public string DataVersion { get; set; }
|
||||
|
||||
public ChannelItemType ChannelItemType { get; set; }
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace MediaBrowser.Controller.Channels
|
|||
{
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
public string ChannelId { get; set; }
|
||||
public string DataVersion { get; set; }
|
||||
|
||||
public ChannelItemType ChannelItemType { get; set; }
|
||||
|
|
|
@ -16,7 +16,6 @@ namespace MediaBrowser.Controller.Channels
|
|||
{
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
public string ChannelId { get; set; }
|
||||
public string DataVersion { get; set; }
|
||||
|
||||
public ChannelItemType ChannelItemType { get; set; }
|
||||
|
|
|
@ -59,6 +59,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel identifier.
|
||||
/// </summary>
|
||||
/// <value>The channel identifier.</value>
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual bool SupportsAddingToPlaylist
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasProgramAttributes
|
||||
{
|
||||
bool IsMovie { get; set; }
|
||||
bool IsSports { get; set; }
|
||||
}
|
||||
}
|
9
MediaBrowser.Controller/Entities/IHasStartDate.cs
Normal file
9
MediaBrowser.Controller/Entities/IHasStartDate.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasStartDate
|
||||
{
|
||||
DateTime StartDate { get; set; }
|
||||
}
|
||||
}
|
|
@ -73,6 +73,17 @@ namespace MediaBrowser.Controller.Entities
|
|||
public string[] Tags { get; set; }
|
||||
public string[] OfficialRatings { get; set; }
|
||||
|
||||
public DateTime? MinStartDate { get; set; }
|
||||
public DateTime? MaxStartDate { get; set; }
|
||||
public DateTime? MinEndDate { get; set; }
|
||||
public DateTime? MaxEndDate { get; set; }
|
||||
public bool? IsAiring { get; set; }
|
||||
|
||||
public bool? IsMovie { get; set; }
|
||||
public bool? IsSports { get; set; }
|
||||
|
||||
public string[] ChannelIds { get; set; }
|
||||
|
||||
public InternalItemsQuery()
|
||||
{
|
||||
Tags = new string[] { };
|
||||
|
@ -89,6 +100,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
Years = new int[] { };
|
||||
PersonTypes = new string[] { };
|
||||
PersonIds = new string[] { };
|
||||
ChannelIds = new string[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.Library
|
||||
{
|
||||
|
@ -132,6 +133,13 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>BaseItem.</returns>
|
||||
BaseItem GetItemById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
QueryResult<BaseItem> GetItems(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the memory item by identifier.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
@ -7,12 +6,10 @@ using MediaBrowser.Model.Users;
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class LiveTvProgram : BaseItem, ILiveTvItem, IHasLookupInfo<LiveTvProgramLookupInfo>
|
||||
public class LiveTvProgram : BaseItem, ILiveTvItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
|
@ -28,12 +25,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// </summary>
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel identifier.
|
||||
/// </summary>
|
||||
/// <value>The channel identifier.</value>
|
||||
public string ExternalChannelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the original air date.
|
||||
/// </summary>
|
||||
|
@ -204,15 +195,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
return "Program";
|
||||
}
|
||||
|
||||
public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
{
|
||||
DateLastSaved = DateTime.UtcNow;
|
||||
|
||||
// Avoid library manager and keep out of in-memory cache
|
||||
// Not great that this class has to know about that, but we'll improve that later.
|
||||
return ItemRepository.SaveItem(this, cancellationToken);
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
|
||||
|
|
|
@ -149,10 +149,12 @@
|
|||
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
||||
<Compile Include="Entities\IHasPreferredMetadataLanguage.cs" />
|
||||
<Compile Include="Entities\IHasProductionLocations.cs" />
|
||||
<Compile Include="Entities\IHasProgramAttributes.cs" />
|
||||
<Compile Include="Entities\IHasScreenshots.cs" />
|
||||
<Compile Include="Entities\IHasSeries.cs" />
|
||||
<Compile Include="Entities\IHasShortOverview.cs" />
|
||||
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
||||
<Compile Include="Entities\IHasStartDate.cs" />
|
||||
<Compile Include="Entities\IHasTaglines.cs" />
|
||||
<Compile Include="Entities\IHasTags.cs" />
|
||||
<Compile Include="Entities\IHasThemeMedia.cs" />
|
||||
|
|
|
@ -4,6 +4,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.Persistence
|
||||
{
|
||||
|
@ -102,13 +103,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <returns>IEnumerable{ChildDefinition}.</returns>
|
||||
IEnumerable<Guid> GetChildren(Guid parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the items of.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>IEnumerable{Guid}.</returns>
|
||||
IEnumerable<Guid> GetItemIdsOfType(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the children.
|
||||
/// </summary>
|
||||
|
@ -135,11 +129,24 @@ namespace MediaBrowser.Controller.Persistence
|
|||
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the items of.
|
||||
/// Gets the item ids.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>IEnumerable<BaseItem>.</returns>
|
||||
IEnumerable<BaseItem> GetItemsOfType(Type type);
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>IEnumerable<Guid>.</returns>
|
||||
QueryResult<Guid> GetItemIds(InternalItemsQuery query);
|
||||
/// <summary>
|
||||
/// Gets the items.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
QueryResult<BaseItem> GetItems(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item ids list.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>List<Guid>.</returns>
|
||||
List<Guid> GetItemIdsList(InternalItemsQuery query);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
using System.Linq;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Providers.Movies;
|
||||
using MediaBrowser.Providers.TV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -23,7 +22,7 @@ using System.Threading.Tasks;
|
|||
namespace MediaBrowser.Providers.Omdb
|
||||
{
|
||||
public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>,
|
||||
IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
|
||||
IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>, IRemoteMetadataProvider<LiveTvProgram, LiveTvProgramLookupInfo>
|
||||
{
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IHttpClient _httpClient;
|
||||
|
@ -48,6 +47,16 @@ namespace MediaBrowser.Providers.Omdb
|
|||
return GetSearchResults(searchInfo, "movie", cancellationToken);
|
||||
}
|
||||
|
||||
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(LiveTvProgramLookupInfo searchInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!searchInfo.IsMovie)
|
||||
{
|
||||
return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
|
||||
}
|
||||
|
||||
return GetSearchResults(searchInfo, "movie", cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken)
|
||||
{
|
||||
var list = new List<RemoteSearchResult>();
|
||||
|
@ -169,13 +178,22 @@ namespace MediaBrowser.Providers.Omdb
|
|||
return result;
|
||||
}
|
||||
|
||||
public Task<MetadataResult<LiveTvProgram>> GetMetadata(LiveTvProgramLookupInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!info.IsMovie)
|
||||
{
|
||||
return Task.FromResult(new MetadataResult<LiveTvProgram>());
|
||||
}
|
||||
return GetMovieResult<LiveTvProgram>(info, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
return GetMovieResult<Movie>(info, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<MetadataResult<T>> GetMovieResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
|
||||
where T : Video, new()
|
||||
where T : BaseItem, new()
|
||||
{
|
||||
var result = new MetadataResult<T>
|
||||
{
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.IO
|
|||
// This is an arbitraty amount of time, but delay it because file system writes often trigger events after RemoveTempIgnore has been called.
|
||||
// Seeing long delays in some situations, especially over the network, sometimes up to 45 seconds
|
||||
// But if we make this delay too high, we risk missing legitimate changes
|
||||
await Task.Delay(10000).ConfigureAwait(false);
|
||||
await Task.Delay(15000).ConfigureAwait(false);
|
||||
|
||||
string val;
|
||||
_tempIgnoredPaths.TryRemove(path, out val);
|
||||
|
|
|
@ -16,6 +16,7 @@ using MediaBrowser.Controller.Sorting;
|
|||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Naming.Audio;
|
||||
using MediaBrowser.Naming.Common;
|
||||
using MediaBrowser.Naming.TV;
|
||||
|
@ -1209,6 +1210,18 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return item;
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||
{
|
||||
var result = ItemRepository.GetItemIdsList(query);
|
||||
|
||||
var items = result.Select(GetItemById).ToArray();
|
||||
|
||||
return new QueryResult<BaseItem>
|
||||
{
|
||||
Items = items
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the intros.
|
||||
/// </summary>
|
||||
|
|
|
@ -17,7 +17,6 @@ using MediaBrowser.Model.Dto;
|
|||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
|
@ -54,10 +53,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
private readonly ConcurrentDictionary<string, LiveStreamData> _openStreams =
|
||||
new ConcurrentDictionary<string, LiveStreamData>();
|
||||
|
||||
private List<Guid> _channelIdList = new List<Guid>();
|
||||
private Dictionary<Guid, LiveTvProgram> _programs;
|
||||
private readonly ConcurrentDictionary<Guid, bool> _refreshedPrograms = new ConcurrentDictionary<Guid, bool>();
|
||||
|
||||
public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager)
|
||||
{
|
||||
_config = config;
|
||||
|
@ -108,44 +103,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
|
||||
}
|
||||
|
||||
private readonly object _programsDataLock = new object();
|
||||
private Dictionary<Guid, LiveTvProgram> GetProgramsDictionary()
|
||||
{
|
||||
if (_programs == null)
|
||||
{
|
||||
lock (_programsDataLock)
|
||||
{
|
||||
if (_programs == null)
|
||||
{
|
||||
var dict = new Dictionary<Guid, LiveTvProgram>();
|
||||
|
||||
foreach (var item in _itemRepo.GetItemsOfType(typeof(LiveTvProgram))
|
||||
.Cast<LiveTvProgram>()
|
||||
.ToList())
|
||||
{
|
||||
dict[item.Id] = item;
|
||||
}
|
||||
|
||||
_programs = dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _programs;
|
||||
}
|
||||
|
||||
private IEnumerable<LiveTvProgram> GetPrograms()
|
||||
{
|
||||
return GetProgramsDictionary().Values;
|
||||
}
|
||||
|
||||
public async Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
||||
|
||||
var channels = _channelIdList.Select(_libraryManager.GetItemById)
|
||||
.Where(i => i != null)
|
||||
.OfType<LiveTvChannel>();
|
||||
var channels = _libraryManager.GetItems(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(LiveTvChannel).Name }
|
||||
|
||||
}).Items.Cast<LiveTvChannel>();
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
|
@ -258,9 +224,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
var returnList = new List<ChannelInfoDto>();
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var programs = _libraryManager.GetItems(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||
MaxStartDate = now,
|
||||
MinEndDate = now
|
||||
|
||||
}).Items.Cast<LiveTvProgram>().OrderBy(i => i.StartDate).ToList();
|
||||
|
||||
foreach (var channel in internalResult.Items)
|
||||
{
|
||||
var currentProgram = GetCurrentProgram(channel.ExternalId);
|
||||
var channelIdString = channel.Id.ToString("N");
|
||||
var currentProgram = programs.FirstOrDefault(i => string.Equals(i.ChannelId, channelIdString, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
returnList.Add(_tvDtoService.GetChannelInfoDto(channel, currentProgram, user));
|
||||
}
|
||||
|
@ -286,34 +263,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
internal LiveTvProgram GetInternalProgram(string id)
|
||||
{
|
||||
var guid = new Guid(id);
|
||||
|
||||
LiveTvProgram obj = null;
|
||||
|
||||
GetProgramsDictionary().TryGetValue(guid, out obj);
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
RefreshIfNeeded(obj);
|
||||
}
|
||||
return obj;
|
||||
return _libraryManager.GetItemById(id) as LiveTvProgram;
|
||||
}
|
||||
|
||||
private void RefreshIfNeeded(LiveTvProgram program)
|
||||
internal LiveTvProgram GetInternalProgram(Guid id)
|
||||
{
|
||||
if (!_refreshedPrograms.ContainsKey(program.Id))
|
||||
{
|
||||
_refreshedPrograms.TryAdd(program.Id, true);
|
||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshIfNeeded(IEnumerable<LiveTvProgram> programs)
|
||||
{
|
||||
foreach (var program in programs)
|
||||
{
|
||||
RefreshIfNeeded(program);
|
||||
}
|
||||
return _libraryManager.GetItemById(id) as LiveTvProgram;
|
||||
}
|
||||
|
||||
public async Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken)
|
||||
|
@ -598,14 +553,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
return item;
|
||||
}
|
||||
|
||||
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
|
||||
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, string channelId, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
|
||||
{
|
||||
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
|
||||
|
||||
var item = _libraryManager.GetItemById(id) as LiveTvProgram;
|
||||
var isNew = false;
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
isNew = true;
|
||||
item = new LiveTvProgram
|
||||
{
|
||||
Name = info.Name,
|
||||
|
@ -619,8 +576,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
item.ServiceName = serviceName;
|
||||
|
||||
item.Audio = info.Audio;
|
||||
item.ExternalChannelId = info.ChannelId;
|
||||
item.CommunityRating = info.CommunityRating;
|
||||
item.ChannelId = channelId;
|
||||
item.CommunityRating = item.CommunityRating ?? info.CommunityRating;
|
||||
item.EndDate = info.EndDate;
|
||||
item.EpisodeTitle = info.EpisodeTitle;
|
||||
item.ExternalId = info.Id;
|
||||
|
@ -636,8 +593,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
item.IsSeries = info.IsSeries;
|
||||
item.IsSports = info.IsSports;
|
||||
item.Name = info.Name;
|
||||
item.OfficialRating = info.OfficialRating;
|
||||
item.Overview = info.Overview;
|
||||
item.OfficialRating = item.OfficialRating ?? info.OfficialRating;
|
||||
item.Overview = item.Overview ?? info.Overview;
|
||||
item.OriginalAirDate = info.OriginalAirDate;
|
||||
item.ProviderImagePath = info.ImagePath;
|
||||
item.ProviderImageUrl = info.ImageUrl;
|
||||
|
@ -647,7 +604,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
item.ProductionYear = info.ProductionYear;
|
||||
item.PremiereDate = item.PremiereDate ?? info.OriginalAirDate;
|
||||
|
||||
await item.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
if (isNew)
|
||||
{
|
||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions());
|
||||
|
||||
return item;
|
||||
}
|
||||
|
@ -721,17 +687,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
return recording;
|
||||
}
|
||||
|
||||
private LiveTvChannel GetChannel(LiveTvProgram program)
|
||||
{
|
||||
var programChannelId = program.ExternalChannelId;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(programChannelId)) return null;
|
||||
|
||||
var internalProgramChannelId = _tvDtoService.GetInternalChannelId(program.ServiceName, programChannelId);
|
||||
|
||||
return GetInternalChannel(internalProgramChannelId);
|
||||
}
|
||||
|
||||
public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null)
|
||||
{
|
||||
var program = GetInternalProgram(id);
|
||||
|
@ -745,55 +700,36 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
public async Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
IEnumerable<LiveTvProgram> programs = GetPrograms();
|
||||
|
||||
if (query.MinEndDate.HasValue)
|
||||
var internalQuery = new InternalItemsQuery
|
||||
{
|
||||
var val = query.MinEndDate.Value;
|
||||
|
||||
programs = programs.Where(i => i.EndDate.HasValue && i.EndDate.Value >= val);
|
||||
}
|
||||
|
||||
if (query.MinStartDate.HasValue)
|
||||
{
|
||||
var val = query.MinStartDate.Value;
|
||||
|
||||
programs = programs.Where(i => i.StartDate >= val);
|
||||
}
|
||||
|
||||
if (query.MaxEndDate.HasValue)
|
||||
{
|
||||
var val = query.MaxEndDate.Value;
|
||||
|
||||
programs = programs.Where(i => i.EndDate.HasValue && i.EndDate.Value <= val);
|
||||
}
|
||||
|
||||
if (query.MaxStartDate.HasValue)
|
||||
{
|
||||
var val = query.MaxStartDate.Value;
|
||||
|
||||
programs = programs.Where(i => i.StartDate <= val);
|
||||
}
|
||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||
MinEndDate = query.MinEndDate,
|
||||
MinStartDate = query.MinStartDate,
|
||||
MaxEndDate = query.MaxEndDate,
|
||||
MaxStartDate = query.MaxStartDate,
|
||||
ChannelIds = query.ChannelIds,
|
||||
IsMovie = query.IsMovie,
|
||||
IsSports = query.IsSports
|
||||
};
|
||||
|
||||
if (query.HasAired.HasValue)
|
||||
{
|
||||
var val = query.HasAired.Value;
|
||||
programs = programs.Where(i => i.HasAired == val);
|
||||
if (query.HasAired.Value)
|
||||
{
|
||||
internalQuery.MaxEndDate = DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalQuery.MinEndDate = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
if (query.ChannelIds.Length > 0)
|
||||
IEnumerable<LiveTvProgram> programs = _libraryManager.GetItems(internalQuery).Items.Cast<LiveTvProgram>();
|
||||
|
||||
// Apply genre filter
|
||||
if (query.Genres.Length > 0)
|
||||
{
|
||||
var guids = query.ChannelIds.Select(i => new Guid(i)).ToList();
|
||||
|
||||
programs = programs.Where(i =>
|
||||
{
|
||||
var programChannelId = i.ExternalChannelId;
|
||||
|
||||
var service = GetService(i);
|
||||
var internalProgramChannelId = _tvDtoService.GetInternalChannelId(service.Name, programChannelId);
|
||||
|
||||
return guids.Contains(internalProgramChannelId);
|
||||
});
|
||||
programs = programs.Where(p => p.Genres.Any(g => query.Genres.Contains(g, StringComparer.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
||||
|
@ -804,22 +740,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
programs = programs.Where(i => i.IsVisible(currentUser));
|
||||
}
|
||||
|
||||
// Apply genre filter
|
||||
if (query.Genres.Length > 0)
|
||||
{
|
||||
programs = programs.Where(p => p.Genres.Any(g => query.Genres.Contains(g, StringComparer.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
if (query.IsMovie.HasValue)
|
||||
{
|
||||
programs = programs.Where(p => p.IsMovie == query.IsMovie);
|
||||
}
|
||||
|
||||
if (query.IsSports.HasValue)
|
||||
{
|
||||
programs = programs.Where(p => p.IsSports == query.IsSports);
|
||||
}
|
||||
|
||||
programs = _libraryManager.Sort(programs, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending)
|
||||
.Cast<LiveTvProgram>();
|
||||
|
||||
|
@ -840,8 +760,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
.Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions(), user))
|
||||
.ToArray();
|
||||
|
||||
RefreshIfNeeded(programList);
|
||||
|
||||
await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var result = new QueryResult<BaseItemDto>
|
||||
|
@ -855,7 +773,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
IEnumerable<LiveTvProgram> programs = GetPrograms();
|
||||
var internalQuery = new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||
IsAiring = query.IsAiring,
|
||||
IsMovie = query.IsMovie,
|
||||
IsSports = query.IsSports
|
||||
};
|
||||
|
||||
if (query.HasAired.HasValue)
|
||||
{
|
||||
if (query.HasAired.Value)
|
||||
{
|
||||
internalQuery.MaxEndDate = DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalQuery.MinEndDate = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<LiveTvProgram> programs = _libraryManager.GetItems(internalQuery).Items.Cast<LiveTvProgram>();
|
||||
|
||||
var user = _userManager.GetUserById(query.UserId);
|
||||
|
||||
|
@ -863,28 +801,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
var currentUser = user;
|
||||
programs = programs.Where(i => i.IsVisible(currentUser));
|
||||
|
||||
if (query.IsAiring.HasValue)
|
||||
{
|
||||
var val = query.IsAiring.Value;
|
||||
programs = programs.Where(i => i.IsAiring == val);
|
||||
}
|
||||
|
||||
if (query.HasAired.HasValue)
|
||||
{
|
||||
var val = query.HasAired.Value;
|
||||
programs = programs.Where(i => i.HasAired == val);
|
||||
}
|
||||
|
||||
if (query.IsMovie.HasValue)
|
||||
{
|
||||
programs = programs.Where(p => p.IsMovie == query.IsMovie.Value);
|
||||
}
|
||||
|
||||
if (query.IsSports.HasValue)
|
||||
{
|
||||
programs = programs.Where(p => p.IsSports == query.IsSports.Value);
|
||||
}
|
||||
|
||||
var programList = programs.ToList();
|
||||
|
||||
var genres = programList.SelectMany(i => i.Genres)
|
||||
|
@ -904,8 +820,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
programList = programs.ToList();
|
||||
|
||||
RefreshIfNeeded(programList);
|
||||
|
||||
var returnArray = programList.ToArray();
|
||||
|
||||
var result = new QueryResult<LiveTvProgram>
|
||||
|
@ -952,8 +866,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
score++;
|
||||
}
|
||||
|
||||
var internalChannelId = _tvDtoService.GetInternalChannelId(program.ServiceName, program.ExternalChannelId);
|
||||
var channel = GetInternalChannel(internalChannelId);
|
||||
var channel = GetInternalChannel(program.ChannelId);
|
||||
|
||||
var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey());
|
||||
|
||||
|
@ -1048,17 +961,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
internal Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
innerProgress.RegisterAction(p => progress.Report(p * .9));
|
||||
await RefreshChannelsInternal(innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
innerProgress = new ActionableProgress<double>();
|
||||
innerProgress.RegisterAction(p => progress.Report(90 + (p * .1)));
|
||||
await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
RefreshIfNeeded(GetPrograms().ToList());
|
||||
return RefreshChannelsInternal(progress, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task RefreshChannelsInternal(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
|
@ -1068,6 +973,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
? 0
|
||||
: 1 / _services.Count;
|
||||
|
||||
var newChannelIdList = new List<Guid>();
|
||||
var newProgramIdList = new List<Guid>();
|
||||
|
||||
foreach (var service in _services)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
@ -1077,7 +985,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
var innerProgress = new ActionableProgress<double>();
|
||||
innerProgress.RegisterAction(p => progress.Report(p * progressPerService));
|
||||
|
||||
await RefreshChannelsInternal(service, innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
var idList = await RefreshChannelsInternal(service, innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
newChannelIdList.AddRange(idList.Item1);
|
||||
newProgramIdList.AddRange(idList.Item2);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -1095,10 +1006,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
progress.Report(100 * percent);
|
||||
}
|
||||
|
||||
await CleanDatabaseInternal(newChannelIdList, typeof(LiveTvChannel).Name, progress, cancellationToken).ConfigureAwait(false);
|
||||
await CleanDatabaseInternal(newProgramIdList, typeof(LiveTvProgram).Name, progress, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Load these now which will prefetch metadata
|
||||
var dtoOptions = new DtoOptions();
|
||||
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
||||
await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private async Task RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
private async Task<Tuple<List<Guid>,List<Guid>>> RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
progress.Report(10);
|
||||
|
||||
|
@ -1137,23 +1056,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
progress.Report(5 * percent + 10);
|
||||
}
|
||||
|
||||
_channelIdList = list.Select(i => i.Id).ToList();
|
||||
progress.Report(15);
|
||||
|
||||
numComplete = 0;
|
||||
var programs = new List<LiveTvProgram>();
|
||||
var programs = new List<Guid>();
|
||||
var channels = new List<Guid>();
|
||||
|
||||
var guideDays = GetGuideDays(list.Count);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var item in list)
|
||||
foreach (var currentChannel in list)
|
||||
{
|
||||
channels.Add(currentChannel.Id);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Avoid implicitly captured closure
|
||||
var currentChannel = item;
|
||||
|
||||
try
|
||||
{
|
||||
var start = DateTime.UtcNow.AddHours(-1);
|
||||
|
@ -1161,9 +1078,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var channelId = currentChannel.Id.ToString("N");
|
||||
|
||||
foreach (var program in channelPrograms)
|
||||
{
|
||||
programs.Add(await GetProgram(program, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false));
|
||||
var programItem = await GetProgram(program, channelId, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
|
||||
programs.Add(programItem.Id);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
|
@ -1181,44 +1101,32 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
progress.Report(80 * percent + 10);
|
||||
}
|
||||
|
||||
lock (_programsDataLock)
|
||||
{
|
||||
_programs = programs.ToDictionary(i => i.Id);
|
||||
}
|
||||
|
||||
_refreshedPrograms.Clear();
|
||||
progress.Report(90);
|
||||
|
||||
// Load these now which will prefetch metadata
|
||||
var dtoOptions = new DtoOptions();
|
||||
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
||||
await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
|
||||
progress.Report(100);
|
||||
|
||||
return new Tuple<List<Guid>,List<Guid>>(channels, programs);
|
||||
}
|
||||
|
||||
private Task CleanDatabaseInternal(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
private async Task CleanDatabaseInternal(List<Guid> currentIdList, string typeName, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return DeleteOldPrograms(GetProgramsDictionary().Keys.ToList(), progress, cancellationToken);
|
||||
}
|
||||
var list = _itemRepo.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeName }
|
||||
|
||||
private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var list = _itemRepo.GetItemIdsOfType(typeof(LiveTvProgram)).ToList();
|
||||
}).Items.ToList();
|
||||
|
||||
var numComplete = 0;
|
||||
|
||||
foreach (var programId in list)
|
||||
foreach (var itemId in list)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (!currentIdList.Contains(programId))
|
||||
if (!currentIdList.Contains(itemId))
|
||||
{
|
||||
var program = _libraryManager.GetItemById(programId);
|
||||
var item = _libraryManager.GetItemById(itemId);
|
||||
|
||||
if (program != null)
|
||||
if (item != null)
|
||||
{
|
||||
await _libraryManager.DeleteItem(program).ConfigureAwait(false);
|
||||
await _libraryManager.DeleteItem(item).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1358,11 +1266,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
var program = (LiveTvProgram)item;
|
||||
var service = GetService(program);
|
||||
|
||||
var channel = string.IsNullOrEmpty(program.ExternalChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, program.ExternalChannelId));
|
||||
var channel = GetInternalChannel(program.ChannelId);
|
||||
|
||||
dto.Id = _tvDtoService.GetInternalProgramId(service.Name, program.ExternalId).ToString("N");
|
||||
|
||||
dto.ChannelId = _tvDtoService.GetInternalChannelId(service.Name, program.ExternalChannelId).ToString("N");
|
||||
dto.ChannelId = channel.Id.ToString("N");
|
||||
|
||||
dto.StartDate = program.StartDate;
|
||||
dto.IsRepeat = program.IsRepeat;
|
||||
|
@ -1676,31 +1584,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
{
|
||||
var channel = GetInternalChannel(id);
|
||||
|
||||
var currentProgram = GetCurrentProgram(channel.ExternalId);
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var programs = _libraryManager.GetItems(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||
ChannelIds = new[] { id },
|
||||
MaxStartDate = now,
|
||||
MinEndDate = now,
|
||||
Limit = 1
|
||||
|
||||
}).Items.Cast<LiveTvProgram>();
|
||||
|
||||
var currentProgram = programs
|
||||
.OrderBy(i => i.StartDate)
|
||||
.FirstOrDefault();
|
||||
|
||||
var dto = _tvDtoService.GetChannelInfoDto(channel, currentProgram, user);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private LiveTvProgram GetCurrentProgram(string externalChannelId)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var program = GetPrograms()
|
||||
.Where(i => string.Equals(externalChannelId, i.ExternalChannelId, StringComparison.OrdinalIgnoreCase))
|
||||
.OrderBy(i => i.StartDate)
|
||||
.SkipWhile(i => now >= (i.EndDate ?? DateTime.MinValue))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (program != null)
|
||||
{
|
||||
RefreshIfNeeded(program);
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
private async Task<Tuple<SeriesTimerInfo, ILiveTvService>> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
|
||||
{
|
||||
var service = program != null && !string.IsNullOrWhiteSpace(program.ServiceName) ?
|
||||
|
@ -1711,10 +1615,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
if (program != null)
|
||||
{
|
||||
var channel = GetInternalChannel(program.ChannelId);
|
||||
|
||||
programInfo = new ProgramInfo
|
||||
{
|
||||
Audio = program.Audio,
|
||||
ChannelId = program.ExternalChannelId,
|
||||
ChannelId = channel.ExternalId,
|
||||
CommunityRating = program.CommunityRating,
|
||||
EndDate = program.EndDate ?? DateTime.MinValue,
|
||||
EpisodeTitle = program.EpisodeTitle,
|
||||
|
@ -1990,15 +1896,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
public GuideInfo GetGuideInfo()
|
||||
{
|
||||
var programs = GetPrograms().OrderBy(i => i.StartDate).ToList();
|
||||
|
||||
var startDate = programs.Count == 0 ?
|
||||
DateTime.MinValue :
|
||||
programs[0].StartDate;
|
||||
|
||||
var endDate = programs.Count == 0 ?
|
||||
DateTime.MinValue :
|
||||
programs[programs.Count - 1].StartDate;
|
||||
var startDate = DateTime.UtcNow;
|
||||
var endDate = startDate.AddDays(14);
|
||||
|
||||
return new GuideInfo
|
||||
{
|
||||
|
|
|
@ -70,7 +70,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
{
|
||||
try
|
||||
{
|
||||
var response = await service.GetProgramImageAsync(liveTvItem.ExternalId, liveTvItem.ExternalChannelId, cancellationToken).ConfigureAwait(false);
|
||||
var channel = _liveTvManager.GetInternalChannel(liveTvItem.ChannelId);
|
||||
|
||||
var response = await service.GetProgramImageAsync(liveTvItem.ExternalId, channel.ExternalId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
@ -126,6 +129,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
_connection.RunQueries(queries, _logger);
|
||||
|
||||
_connection.AddColumn(_logger, "TypedBaseItems", "StartDate", "DATETIME");
|
||||
_connection.AddColumn(_logger, "TypedBaseItems", "EndDate", "DATETIME");
|
||||
_connection.AddColumn(_logger, "TypedBaseItems", "ChannelId", "Text");
|
||||
_connection.AddColumn(_logger, "TypedBaseItems", "IsMovie", "BIT");
|
||||
_connection.AddColumn(_logger, "TypedBaseItems", "IsSports", "BIT");
|
||||
|
||||
PrepareStatements();
|
||||
|
||||
_mediaStreamsRepository.Initialize();
|
||||
|
@ -143,10 +152,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
private void PrepareStatements()
|
||||
{
|
||||
_saveItemCommand = _connection.CreateCommand();
|
||||
_saveItemCommand.CommandText = "replace into TypedBaseItems (guid, type, data) values (@1, @2, @3)";
|
||||
_saveItemCommand.CommandText = "replace into TypedBaseItems (guid, type, data, StartDate, EndDate, ChannelId, IsMovie, IsSports) values (@1, @2, @3, @4, @5, @6, @7, @8)";
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@1");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@2");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@3");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@4");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@5");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@6");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@7");
|
||||
_saveItemCommand.Parameters.Add(_saveItemCommand, "@8");
|
||||
|
||||
_deleteChildrenCommand = _connection.CreateCommand();
|
||||
_deleteChildrenCommand.CommandText = "delete from ChildrenIds where ParentId=@ParentId";
|
||||
|
@ -155,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_deleteItemCommand = _connection.CreateCommand();
|
||||
_deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id";
|
||||
_deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id");
|
||||
|
||||
|
||||
_saveChildrenCommand = _connection.CreateCommand();
|
||||
_saveChildrenCommand.CommandText = "replace into ChildrenIds (ParentId, ItemId) values (@ParentId, @ItemId)";
|
||||
_saveChildrenCommand.Parameters.Add(_saveChildrenCommand, "@ParentId");
|
||||
|
@ -200,7 +214,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
IDbTransaction transaction = null;
|
||||
|
@ -217,6 +231,31 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_saveItemCommand.GetParameter(1).Value = item.GetType().FullName;
|
||||
_saveItemCommand.GetParameter(2).Value = _jsonSerializer.SerializeToBytes(item);
|
||||
|
||||
var hasStartDate = item as IHasStartDate;
|
||||
if (hasStartDate != null)
|
||||
{
|
||||
_saveItemCommand.GetParameter(3).Value = hasStartDate.StartDate;
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveItemCommand.GetParameter(3).Value = null;
|
||||
}
|
||||
|
||||
_saveItemCommand.GetParameter(4).Value = item.EndDate;
|
||||
_saveItemCommand.GetParameter(5).Value = item.ChannelId;
|
||||
|
||||
var hasProgramAttributes = item as IHasProgramAttributes;
|
||||
if (hasProgramAttributes != null)
|
||||
{
|
||||
_saveItemCommand.GetParameter(6).Value = hasProgramAttributes.IsMovie;
|
||||
_saveItemCommand.GetParameter(7).Value = hasProgramAttributes.IsSports;
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveItemCommand.GetParameter(6).Value = null;
|
||||
_saveItemCommand.GetParameter(7).Value = null;
|
||||
}
|
||||
|
||||
_saveItemCommand.Transaction = transaction;
|
||||
|
||||
_saveItemCommand.ExecuteNonQuery();
|
||||
|
@ -254,7 +293,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_writeLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Internal retrieve from items or users table
|
||||
/// </summary>
|
||||
|
@ -270,7 +309,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems where guid = @guid";
|
||||
|
@ -467,7 +506,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select ItemId from ChildrenIds where ParentId = @ParentId";
|
||||
|
@ -492,7 +531,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
|
||||
|
@ -544,6 +583,279 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
{
|
||||
throw new ArgumentNullException("query");
|
||||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems";
|
||||
|
||||
var whereClauses = GetWhereClauses(query, cmd, false);
|
||||
|
||||
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
whereClauses = GetWhereClauses(query, cmd, true);
|
||||
|
||||
var whereText = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
cmd.CommandText += whereText;
|
||||
|
||||
if (query.Limit.HasValue)
|
||||
{
|
||||
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
var count = 0;
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
list.Add(GetItem(reader));
|
||||
}
|
||||
|
||||
if (reader.NextResult() && reader.Read())
|
||||
{
|
||||
count = reader.GetInt32(0);
|
||||
}
|
||||
}
|
||||
|
||||
return new QueryResult<BaseItem>()
|
||||
{
|
||||
Items = list.ToArray(),
|
||||
TotalRecordCount = count
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public List<Guid> GetItemIdsList(InternalItemsQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
{
|
||||
throw new ArgumentNullException("query");
|
||||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select guid from TypedBaseItems";
|
||||
|
||||
var whereClauses = GetWhereClauses(query, cmd, false);
|
||||
|
||||
whereClauses = GetWhereClauses(query, cmd, true);
|
||||
|
||||
var whereText = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
cmd.CommandText += whereText;
|
||||
|
||||
if (query.Limit.HasValue)
|
||||
{
|
||||
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
var list = new List<Guid>();
|
||||
|
||||
_logger.Debug(cmd.CommandText);
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
list.Add(reader.GetGuid(0));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public QueryResult<Guid> GetItemIds(InternalItemsQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
{
|
||||
throw new ArgumentNullException("query");
|
||||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select guid from TypedBaseItems";
|
||||
|
||||
var whereClauses = GetWhereClauses(query, cmd, false);
|
||||
|
||||
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
whereClauses = GetWhereClauses(query, cmd, true);
|
||||
|
||||
var whereText = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
cmd.CommandText += whereText;
|
||||
|
||||
if (query.Limit.HasValue)
|
||||
{
|
||||
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
||||
|
||||
var list = new List<Guid>();
|
||||
var count = 0;
|
||||
|
||||
_logger.Debug(cmd.CommandText);
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
list.Add(reader.GetGuid(0));
|
||||
}
|
||||
|
||||
if (reader.NextResult() && reader.Read())
|
||||
{
|
||||
count = reader.GetInt32(0);
|
||||
}
|
||||
}
|
||||
|
||||
return new QueryResult<Guid>()
|
||||
{
|
||||
Items = list.ToArray(),
|
||||
TotalRecordCount = count
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging)
|
||||
{
|
||||
var whereClauses = new List<string>();
|
||||
|
||||
if (query.IsMovie.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsMovie=@IsMovie");
|
||||
cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie;
|
||||
}
|
||||
if (query.IsSports.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsSports=@IsSports");
|
||||
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
|
||||
}
|
||||
if (query.IncludeItemTypes.Length == 1)
|
||||
{
|
||||
whereClauses.Add("type=@type");
|
||||
cmd.Parameters.Add(cmd, "@type", DbType.String).Value = MapIncludeItemType(query.IncludeItemTypes[0]);
|
||||
}
|
||||
if (query.IncludeItemTypes.Length > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.IncludeItemTypes.Select(i => "'" + MapIncludeItemType(i) + "'").ToArray());
|
||||
whereClauses.Add(string.Format("type in ({0})", inClause));
|
||||
}
|
||||
if (query.ChannelIds.Length == 1)
|
||||
{
|
||||
whereClauses.Add("ChannelId=@ChannelId");
|
||||
cmd.Parameters.Add(cmd, "@ChannelId", DbType.String).Value = query.ChannelIds[0];
|
||||
}
|
||||
if (query.ChannelIds.Length > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i + "'").ToArray());
|
||||
whereClauses.Add(string.Format("ChannelId in ({0})", inClause));
|
||||
}
|
||||
|
||||
if (query.MinEndDate.HasValue)
|
||||
{
|
||||
whereClauses.Add("EndDate>=@MinEndDate");
|
||||
cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = query.MinEndDate.Value;
|
||||
}
|
||||
|
||||
if (query.MaxEndDate.HasValue)
|
||||
{
|
||||
whereClauses.Add("EndDate<=@MaxEndDate");
|
||||
cmd.Parameters.Add(cmd, "@MaxEndDate", DbType.Date).Value = query.MaxEndDate.Value;
|
||||
}
|
||||
|
||||
if (query.MinStartDate.HasValue)
|
||||
{
|
||||
whereClauses.Add("StartDate>=@MinStartDate");
|
||||
cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value;
|
||||
}
|
||||
|
||||
if (query.MaxStartDate.HasValue)
|
||||
{
|
||||
whereClauses.Add("StartDate<=@MaxStartDate");
|
||||
cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = query.MaxStartDate.Value;
|
||||
}
|
||||
|
||||
if (query.IsAiring.HasValue)
|
||||
{
|
||||
if (query.IsAiring.Value)
|
||||
{
|
||||
whereClauses.Add("StartDate<=@MaxStartDate");
|
||||
cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = DateTime.UtcNow;
|
||||
|
||||
whereClauses.Add("EndDate>=@MinEndDate");
|
||||
cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("(StartDate>@IsAiringDate OR EndDate < @IsAiringDate)");
|
||||
cmd.Parameters.Add(cmd, "@IsAiringDate", DbType.Date).Value = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
if (addPaging)
|
||||
{
|
||||
if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
|
||||
{
|
||||
var pagingWhereText = whereClauses.Count == 0 ?
|
||||
string.Empty :
|
||||
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||
|
||||
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM TypedBaseItems {0} ORDER BY DateCreated DESC LIMIT {1})",
|
||||
pagingWhereText,
|
||||
query.StartIndex.Value.ToString(CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
return whereClauses;
|
||||
}
|
||||
|
||||
// Not crazy about having this all the way down here, but at least it's in one place
|
||||
readonly Dictionary<string, string> _types = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{typeof(LiveTvProgram).Name, typeof(LiveTvProgram).FullName},
|
||||
{typeof(LiveTvChannel).Name, typeof(LiveTvChannel).FullName}
|
||||
};
|
||||
|
||||
private string MapIncludeItemType(string value)
|
||||
{
|
||||
string result;
|
||||
if (_types.TryGetValue(value, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public IEnumerable<Guid> GetItemIdsOfType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
|
@ -577,7 +889,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
IDbTransaction transaction = null;
|
||||
|
@ -595,7 +907,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_deleteItemCommand.GetParameter(0).Value = id;
|
||||
_deleteItemCommand.Transaction = transaction;
|
||||
_deleteItemCommand.ExecuteNonQuery();
|
||||
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
|
@ -642,7 +954,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
|
||||
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
IDbTransaction transaction = null;
|
||||
|
|
Loading…
Reference in New Issue
Block a user