aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs')
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs387
1 files changed, 303 insertions, 84 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index f6c69d8d6..d73b144b8 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
@@ -13,15 +14,18 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Sorting;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
+using MoreLinq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -55,7 +59,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
- 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)
+ private readonly List<ITunerHost> _tunerHosts = new List<ITunerHost>();
+ private readonly List<IListingsProvider> _listingProviders = new List<IListingsProvider>();
+ private readonly IFileSystem _fileSystem;
+
+ 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, IFileSystem fileSystem)
{
_config = config;
_logger = logger;
@@ -66,6 +74,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_localization = localization;
_jsonSerializer = jsonSerializer;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
_dtoService = dtoService;
_userDataManager = userDataManager;
@@ -90,9 +99,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
/// Adds the parts.
/// </summary>
/// <param name="services">The services.</param>
- public void AddParts(IEnumerable<ILiveTvService> services)
+ /// <param name="tunerHosts">The tuner hosts.</param>
+ /// <param name="listingProviders">The listing providers.</param>
+ public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
{
_services.AddRange(services);
+ _tunerHosts.AddRange(tunerHosts);
+ _listingProviders.AddRange(listingProviders);
foreach (var service in _services)
{
@@ -100,6 +113,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
+ public List<ITunerHost> TunerHosts
+ {
+ get { return _tunerHosts; }
+ }
+
+ public List<IListingsProvider> ListingProviders
+ {
+ get { return _listingProviders; }
+ }
+
void service_DataSourceChanged(object sender, EventArgs e)
{
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
@@ -218,7 +241,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return result;
}
- public async Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, DtoOptions options, CancellationToken cancellationToken)
{
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
@@ -228,20 +251,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var now = DateTime.UtcNow;
- var programs = _libraryManager.GetItems(new InternalItemsQuery
+ var programs = query.AddCurrentProgram ? _libraryManager.QueryItems(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
MaxStartDate = now,
- MinEndDate = now
+ MinEndDate = now,
+ ChannelIds = internalResult.Items.Select(i => i.Id.ToString("N")).ToArray()
- }).Items.Cast<LiveTvProgram>().OrderBy(i => i.StartDate).ToList();
+ }).Items.Cast<LiveTvProgram>().OrderBy(i => i.StartDate).ToList() : new List<LiveTvProgram>();
foreach (var channel in internalResult.Items)
{
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));
+ returnList.Add(_tvDtoService.GetChannelInfoDto(channel, options, currentProgram, user));
}
var result = new QueryResult<ChannelInfoDto>
@@ -310,6 +334,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var service = GetService(item);
var sources = await service.GetChannelStreamMediaSources(item.ExternalId, cancellationToken).ConfigureAwait(false);
+
+ if (sources.Count == 0)
+ {
+ throw new NotImplementedException();
+ }
+
var list = sources.ToList();
foreach (var source in list)
@@ -334,6 +364,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
+ if (string.Equals(id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
+ {
+ mediaSourceId = null;
+ }
+
try
{
MediaSourceInfo info;
@@ -525,16 +560,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var replaceImages = new List<ImageType>();
- if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase))
- {
- isNew = true;
- replaceImages.Add(ImageType.Primary);
- }
- if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase))
- {
- isNew = true;
- replaceImages.Add(ImageType.Primary);
- }
+ //if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase))
+ //{
+ // isNew = true;
+ // replaceImages.Add(ImageType.Primary);
+ //}
+ //if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase))
+ //{
+ // isNew = true;
+ // replaceImages.Add(ImageType.Primary);
+ //}
item.ProviderImageUrl = channelInfo.ImageUrl;
item.HasProviderImage = channelInfo.HasImage;
@@ -570,7 +605,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
Name = info.Name,
Id = id,
DateCreated = DateTime.UtcNow,
- DateModified = DateTime.UtcNow
+ DateModified = DateTime.UtcNow,
+ Etag = info.Etag
};
}
@@ -602,17 +638,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv
item.ProviderImageUrl = info.ImageUrl;
item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks;
item.StartDate = info.StartDate;
+ item.HomePageUrl = info.HomePageUrl;
item.ProductionYear = info.ProductionYear;
item.PremiereDate = item.PremiereDate ?? info.OriginalAirDate;
+ item.IndexNumber = info.EpisodeNumber;
+ item.ParentIndexNumber = info.SeasonNumber;
+
if (isNew)
{
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
}
else
{
- await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
+ if (string.IsNullOrWhiteSpace(info.Etag) || !string.Equals(info.Etag, item.Etag, StringComparison.OrdinalIgnoreCase))
+ {
+ item.Etag = info.Etag;
+ await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
+ }
}
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions());
@@ -694,6 +738,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (!string.IsNullOrEmpty(info.Path))
{
item.Path = info.Path;
+ var fileInfo = new FileInfo(info.Path);
+
+ recording.DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo);
+ recording.DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo);
}
else if (!string.IsNullOrEmpty(info.Url))
{
@@ -706,7 +754,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
}
- else if (pathChanged)
+ else if (pathChanged || info.DateLastUpdated > recording.DateLastSaved)
{
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
}
@@ -727,7 +775,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return dto;
}
- public async Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
{
var internalQuery = new InternalItemsQuery
{
@@ -738,9 +786,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv
MaxStartDate = query.MaxStartDate,
ChannelIds = query.ChannelIds,
IsMovie = query.IsMovie,
- IsSports = query.IsSports
+ IsSports = query.IsSports,
+ IsKids = query.IsKids,
+ Genres = query.Genres,
+ StartIndex = query.StartIndex,
+ Limit = query.Limit,
+ SortBy = query.SortBy,
+ SortOrder = query.SortOrder ?? SortOrder.Ascending
};
+ var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+ if (user != null)
+ {
+ internalQuery.MaxParentalRating = user.Policy.MaxParentalRating;
+
+ if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram))
+ {
+ internalQuery.HasParentalRating = true;
+ }
+ }
+
if (query.HasAired.HasValue)
{
if (query.HasAired.Value)
@@ -753,40 +818,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
- IEnumerable<LiveTvProgram> programs = _libraryManager.GetItems(internalQuery).Items.Cast<LiveTvProgram>();
-
- // Apply genre filter
- if (query.Genres.Length > 0)
- {
- 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);
- if (user != null)
- {
- // Avoid implicitly captured closure
- var currentUser = user;
- programs = programs.Where(i => i.IsVisible(currentUser));
- }
-
- programs = _libraryManager.Sort(programs, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending)
- .Cast<LiveTvProgram>();
-
- var programList = programs.ToList();
- IEnumerable<LiveTvProgram> returnPrograms = programList;
-
- if (query.StartIndex.HasValue)
- {
- returnPrograms = returnPrograms.Skip(query.StartIndex.Value);
- }
-
- if (query.Limit.HasValue)
- {
- returnPrograms = returnPrograms.Take(query.Limit.Value);
- }
+ var queryResult = _libraryManager.QueryItems(internalQuery);
- var returnArray = returnPrograms
- .Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions(), user))
+ var returnArray = queryResult.Items
+ .Select(i => _dtoService.GetBaseItemDto(i, options, user))
.ToArray();
await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false);
@@ -794,7 +829,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var result = new QueryResult<BaseItemDto>
{
Items = returnArray,
- TotalRecordCount = programList.Count
+ TotalRecordCount = queryResult.TotalRecordCount
};
return result;
@@ -807,7 +842,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
IsAiring = query.IsAiring,
IsMovie = query.IsMovie,
- IsSports = query.IsSports
+ IsSports = query.IsSports,
+ IsKids = query.IsKids
};
if (query.HasAired.HasValue)
@@ -822,19 +858,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
- IEnumerable<LiveTvProgram> programs = _libraryManager.GetItems(internalQuery).Items.Cast<LiveTvProgram>();
-
var user = _userManager.GetUserById(query.UserId);
+ if (user != null)
+ {
+ internalQuery.MaxParentalRating = user.Policy.MaxParentalRating;
+
+ if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram))
+ {
+ internalQuery.HasParentalRating = true;
+ }
+ }
- // Avoid implicitly captured closure
- var currentUser = user;
- programs = programs.Where(i => i.IsVisible(currentUser));
+ IEnumerable<LiveTvProgram> programs = _libraryManager.QueryItems(internalQuery).Items.Cast<LiveTvProgram>();
var programList = programs.ToList();
var genres = programList.SelectMany(i => i.Genres)
+ .Where(i => !string.IsNullOrWhiteSpace(i))
.DistinctNames()
.Select(i => _libraryManager.GetGenre(i))
+ .DistinctBy(i => i.Id)
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
programs = programList.OrderBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
@@ -843,8 +886,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (query.Limit.HasValue)
{
- programs = programs.Take(query.Limit.Value)
- .OrderBy(i => i.StartDate);
+ programs = programs.Take(query.Limit.Value);
}
programList = programs.ToList();
@@ -860,14 +902,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return result;
}
- public async Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
{
var internalResult = await GetRecommendedProgramsInternal(query, cancellationToken).ConfigureAwait(false);
var user = _userManager.GetUserById(query.UserId);
var returnArray = internalResult.Items
- .Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions(), user))
+ .Select(i => _dtoService.GetBaseItemDto(i, options, user))
.ToArray();
await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false);
@@ -1009,6 +1051,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
cancellationToken.ThrowIfCancellationRequested();
+ _logger.Debug("Refreshing guide from {0}", service.Name);
+
try
{
var innerProgress = new ActionableProgress<double>();
@@ -1340,21 +1384,45 @@ namespace MediaBrowser.Server.Implementations.LiveTv
dto.Id = _tvDtoService.GetInternalProgramId(service.Name, program.ExternalId).ToString("N");
- dto.ChannelId = item.ChannelId;
-
dto.StartDate = program.StartDate;
dto.IsRepeat = program.IsRepeat;
dto.EpisodeTitle = program.EpisodeTitle;
dto.ChannelType = program.ChannelType;
dto.Audio = program.Audio;
- dto.IsHD = program.IsHD;
- dto.IsMovie = program.IsMovie;
- dto.IsSeries = program.IsSeries;
- dto.IsSports = program.IsSports;
- dto.IsLive = program.IsLive;
- dto.IsNews = program.IsNews;
- dto.IsKids = program.IsKids;
- dto.IsPremiere = program.IsPremiere;
+
+ if (program.IsHD.HasValue && program.IsHD.Value)
+ {
+ dto.IsHD = program.IsHD;
+ }
+ if (program.IsMovie)
+ {
+ dto.IsMovie = program.IsMovie;
+ }
+ if (program.IsSeries)
+ {
+ dto.IsSeries = program.IsSeries;
+ }
+ if (program.IsSports)
+ {
+ dto.IsSports = program.IsSports;
+ }
+ if (program.IsLive)
+ {
+ dto.IsLive = program.IsLive;
+ }
+ if (program.IsNews)
+ {
+ dto.IsNews = program.IsNews;
+ }
+ if (program.IsKids)
+ {
+ dto.IsKids = program.IsKids;
+ }
+ if (program.IsPremiere)
+ {
+ dto.IsPremiere = program.IsPremiere;
+ }
+
dto.OriginalAirDate = program.OriginalAirDate;
if (channel != null)
@@ -1382,8 +1450,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
? null
: _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
- dto.ChannelId = item.ChannelId;
-
dto.StartDate = info.StartDate;
dto.RecordingStatus = info.Status;
dto.IsRepeat = info.IsRepeat;
@@ -1663,11 +1729,37 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate)
.FirstOrDefault();
- var dto = _tvDtoService.GetChannelInfoDto(channel, currentProgram, user);
+ var dto = _tvDtoService.GetChannelInfoDto(channel, new DtoOptions(), currentProgram, user);
return dto;
}
+ public void AddChannelInfo(BaseItemDto dto, LiveTvChannel channel, DtoOptions options, User user)
+ {
+ dto.MediaSources = channel.GetMediaSources(true).ToList();
+
+ var now = DateTime.UtcNow;
+
+ var programs = _libraryManager.GetItems(new InternalItemsQuery
+ {
+ IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
+ ChannelIds = new[] { channel.Id.ToString("N") },
+ MaxStartDate = now,
+ MinEndDate = now,
+ Limit = 1
+
+ }).Items.Cast<LiveTvProgram>();
+
+ var currentProgram = programs
+ .OrderBy(i => i.StartDate)
+ .FirstOrDefault();
+
+ if (currentProgram != null)
+ {
+ dto.CurrentProgram = _dtoService.GetBaseItemDto(currentProgram, options, user);
+ }
+ }
+
private async Task<Tuple<SeriesTimerInfo, ILiveTvService>> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
{
var service = program != null && !string.IsNullOrWhiteSpace(program.ServiceName) ?
@@ -2029,6 +2121,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
info.Version = statusInfo.Version;
info.HasUpdateAvailable = statusInfo.HasUpdateAvailable;
info.HomePageUrl = service.HomePageUrl;
+ info.IsVisible = statusInfo.IsVisible;
info.Tuners = statusInfo.Tuners.Select(i =>
{
@@ -2081,7 +2174,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private bool IsLiveTvEnabled(User user)
{
- return user.Policy.EnableLiveTvAccess && Services.Count > 0;
+ return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Count(i => i.IsEnabled) > 0);
}
public IEnumerable<User> GetEnabledUsers()
@@ -2114,16 +2207,142 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId);
- var folder = await GetInternalLiveTvFolder(userId, cancellationToken).ConfigureAwait(false);
+ var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
return _dtoService.GetBaseItemDto(folder, new DtoOptions(), user);
}
- public async Task<Folder> GetInternalLiveTvFolder(string userId, CancellationToken cancellationToken)
+ public async Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken)
{
var name = _localization.GetLocalizedString("ViewTypeLiveTV");
- var user = _userManager.GetUserById(userId);
- return await _libraryManager.GetNamedView(user, name, "livetv", "zz_" + name, cancellationToken).ConfigureAwait(false);
+ return await _libraryManager.GetNamedView(name, "livetv", name, cancellationToken).ConfigureAwait(false);
+ }
+
+ public async Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info)
+ {
+ info = (TunerHostInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(TunerHostInfo));
+
+ var provider = _tunerHosts.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase));
+
+ if (provider == null)
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ await provider.Validate(info).ConfigureAwait(false);
+
+ var config = GetConfiguration();
+
+ var index = config.TunerHosts.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+
+ if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
+ {
+ info.Id = Guid.NewGuid().ToString("N");
+ config.TunerHosts.Add(info);
+ }
+ else
+ {
+ config.TunerHosts[index] = info;
+ }
+
+ _config.SaveConfiguration("livetv", config);
+
+ _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
+
+ return info;
+ }
+
+ public async Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings)
+ {
+ info = (ListingsProviderInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(ListingsProviderInfo));
+
+ var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase));
+
+ if (provider == null)
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false);
+
+ var config = GetConfiguration();
+
+ var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+
+ if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
+ {
+ info.Id = Guid.NewGuid().ToString("N");
+ config.ListingProviders.Add(info);
+ }
+ else
+ {
+ config.ListingProviders[index] = info;
+ }
+
+ _config.SaveConfiguration("livetv", config);
+
+ _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
+
+ return info;
+ }
+
+ public Task<List<NameIdPair>> GetLineups(string providerType, string providerId, string country, string location)
+ {
+ var config = GetConfiguration();
+
+ if (string.IsNullOrWhiteSpace(providerId))
+ {
+ var provider = _listingProviders.FirstOrDefault(i => string.Equals(providerType, i.Type, StringComparison.OrdinalIgnoreCase));
+
+ if (provider == null)
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ return provider.GetLineups(null, country, location);
+ }
+ else
+ {
+ var info = config.ListingProviders.FirstOrDefault(i => string.Equals(i.Id, providerId, StringComparison.OrdinalIgnoreCase));
+
+ var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase));
+
+ if (provider == null)
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ return provider.GetLineups(info, country, location);
+ }
+ }
+
+ public Task<MBRegistrationRecord> GetRegistrationInfo(string channelId, string programId, string feature)
+ {
+ ILiveTvService service;
+
+ if (string.IsNullOrWhiteSpace(programId))
+ {
+ var channel = GetInternalChannel(channelId);
+ service = GetService(channel);
+ }
+ else
+ {
+ var program = GetInternalProgram(programId);
+ service = GetService(program);
+ }
+
+ var hasRegistration = service as IHasRegistrationInfo;
+
+ if (hasRegistration != null)
+ {
+ return hasRegistration.GetRegistrationInfo(feature);
+ }
+
+ return Task.FromResult(new MBRegistrationRecord
+ {
+ IsValid = true,
+ IsRegistered = true
+ });
}
}
}