diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-11-24 15:51:45 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-11-24 15:51:45 -0500 |
| commit | 7b6819846d464c9e67335cfb6ab230702eb6ba1d (patch) | |
| tree | 59eca1ce1190898d7c09b332139fdd57b43d3e4e /MediaBrowser.Server.Implementations | |
| parent | a99a10c02bbf34b9745a5170e3c468216de649bd (diff) | |
updated live tv + nuget
Diffstat (limited to 'MediaBrowser.Server.Implementations')
5 files changed, 321 insertions, 9 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs new file mode 100644 index 000000000..4ab6e55c8 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -0,0 +1,100 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using System; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.LiveTv +{ + public class ChannelImageProvider : BaseMetadataProvider + { + private readonly ILiveTvManager _liveTvManager; + private readonly IProviderManager _providerManager; + + public ChannelImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, ILiveTvManager liveTvManager, IProviderManager providerManager) + : base(logManager, configurationManager) + { + _liveTvManager = liveTvManager; + _providerManager = providerManager; + } + + public override bool Supports(BaseItem item) + { + return item is Channel; + } + + protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) + { + if (item.HasImage(ImageType.Primary)) + { + return false; + } + + return base.NeedsRefreshInternal(item, providerInfo); + } + + public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + { + if (item.HasImage(ImageType.Primary)) + { + SetLastRefreshed(item, DateTime.UtcNow); + return true; + } + + try + { + await DownloadImage(item, cancellationToken).ConfigureAwait(false); + } + catch (HttpException ex) + { + // Don't fail the provider on a 404 + if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) + { + throw; + } + } + + + SetLastRefreshed(item, DateTime.UtcNow); + return true; + } + + private async Task DownloadImage(BaseItem item, CancellationToken cancellationToken) + { + var channel = (Channel)item; + + var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, channel.ServiceName, StringComparison.OrdinalIgnoreCase)); + + if (service != null) + { + var response = await service.GetChannelImageAsync(channel.ChannelId, cancellationToken).ConfigureAwait(false); + + // Dummy up the original url + var url = channel.ServiceName + channel.ChannelId; + + await _providerManager.SaveImage(channel, response.Content, response.ContentType, ImageType.Primary, null, url, cancellationToken).ConfigureAwait(false); + } + } + + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.Second; } + } + + public override ItemUpdateType ItemUpdateType + { + get + { + return ItemUpdateType.ImageUpdate; + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 05bac17c3..9e1c6c4ac 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,6 +1,18 @@ -using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Logging; +using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.LiveTv { @@ -9,7 +21,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv /// </summary> public class LiveTvManager : ILiveTvManager { + private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; + private readonly IItemRepository _itemRepo; + private readonly IImageProcessor _imageProcessor; + + private List<Channel> _channels = new List<Channel>(); + private readonly List<ILiveTvService> _services = new List<ILiveTvService>(); + + public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor) + { + _appPaths = appPaths; + _fileSystem = fileSystem; + _logger = logger; + _itemRepo = itemRepo; + _imageProcessor = imageProcessor; + } + /// <summary> /// Gets the services. /// </summary> @@ -33,16 +63,147 @@ namespace MediaBrowser.Server.Implementations.LiveTv /// </summary> /// <param name="info">The info.</param> /// <returns>ChannelInfoDto.</returns> - public ChannelInfoDto GetChannelInfoDto(ChannelInfo info) + public ChannelInfoDto GetChannelInfoDto(Channel info) { return new ChannelInfoDto { Name = info.Name, ServiceName = info.ServiceName, ChannelType = info.ChannelType, - Id = info.Id, - Number = info.Number + Id = info.ChannelId, + Number = info.ChannelNumber, + PrimaryImageTag = GetLogoImageTag(info) }; } + + private Guid? GetLogoImageTag(Channel info) + { + var path = info.PrimaryImagePath; + + if (string.IsNullOrEmpty(path)) + { + return null; + } + + try + { + return _imageProcessor.GetImageCacheTag(info, ImageType.Primary, path); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting channel image info for {0}", ex, info.Name); + } + + return null; + } + + public IEnumerable<Channel> GetChannels(ChannelQuery query) + { + return _channels.OrderBy(i => + { + double number = 0; + + if (!string.IsNullOrEmpty(i.ChannelNumber)) + { + double.TryParse(i.ChannelNumber, out number); + } + + return number; + + }).ThenBy(i => i.Name); + } + + public Channel GetChannel(string serviceName, string channelId) + { + return _channels.FirstOrDefault(i => string.Equals(i.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase) && string.Equals(i.ChannelId, channelId, StringComparison.OrdinalIgnoreCase)); + } + + internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) + { + // Avoid implicitly captured closure + var currentCancellationToken = cancellationToken; + + var tasks = _services.Select(i => i.GetChannelsAsync(currentCancellationToken)); + + var results = await Task.WhenAll(tasks).ConfigureAwait(false); + + var allChannels = results.SelectMany(i => i); + + var channnelTasks = allChannels.Select(i => GetChannel(i, cancellationToken)); + + var channelEntities = await Task.WhenAll(channnelTasks).ConfigureAwait(false); + + _channels = channelEntities.ToList(); + } + + private async Task<Channel> GetChannel(ChannelInfo channelInfo, CancellationToken cancellationToken) + { + try + { + return await GetChannelInternal(channelInfo, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Name); + + return null; + } + } + + private async Task<Channel> GetChannelInternal(ChannelInfo channelInfo, CancellationToken cancellationToken) + { + var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.ServiceName), _fileSystem.GetValidFilename(channelInfo.Name)); + + var fileInfo = new DirectoryInfo(path); + + var isNew = false; + + if (!fileInfo.Exists) + { + Directory.CreateDirectory(path); + fileInfo = new DirectoryInfo(path); + + if (!fileInfo.Exists) + { + throw new IOException("Path not created: " + path); + } + + isNew = true; + } + + var type = typeof(Channel); + + var id = (path + channelInfo.Number).GetMBId(type); + + var item = _itemRepo.RetrieveItem(id) as Channel; + + if (item == null) + { + item = new Channel + { + Name = channelInfo.Name, + Id = id, + DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo), + DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo), + Path = path, + ChannelId = channelInfo.Id, + ChannelNumber = channelInfo.Number, + ServiceName = channelInfo.ServiceName + }; + + isNew = true; + } + + // Set this now so we don't cause additional file system access during provider executions + item.ResetResolveArgs(fileInfo); + + await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false); + + return item; + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs new file mode 100644 index 000000000..d5e10bb37 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -0,0 +1,54 @@ +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Tasks; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.LiveTv +{ + class RefreshChannelsScheduledTask : IScheduledTask + { + private readonly ILiveTvManager _liveTvManager; + + public RefreshChannelsScheduledTask(ILiveTvManager liveTvManager) + { + _liveTvManager = liveTvManager; + } + + public string Name + { + get { return "Refresh Channels"; } + } + + public string Description + { + get { return "Downloads channel information from live tv services."; } + } + + public string Category + { + get { return "Live TV"; } + } + + public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress) + { + var manager = (LiveTvManager) _liveTvManager; + + return manager.RefreshChannels(progress, cancellationToken); + } + + public IEnumerable<ITaskTrigger> GetDefaultTriggers() + { + return new ITaskTrigger[] + { + + new StartupTrigger(), + + new SystemEventTrigger{ SystemEvent = SystemEvent.WakeFromSleep}, + + new IntervalTrigger{ Interval = TimeSpan.FromHours(4)} + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt index e551223a8..5a110648c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt +++ b/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt @@ -1,11 +1,6 @@ CA-G,1 -GB-U,1 CA-PG,5 -DE-0,5 CA-14A,7 -DE-12,7 CA-A,8 CA-18A,9 -SE-11,9 -DE-16,9 CA-R,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 9347ea0eb..f5ade2516 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -167,7 +167,9 @@ <Compile Include="Library\Validators\StudiosPostScanTask.cs" /> <Compile Include="Library\Validators\StudiosValidator.cs" /> <Compile Include="Library\Validators\YearsPostScanTask.cs" /> + <Compile Include="LiveTv\ChannelImageProvider.cs" /> <Compile Include="LiveTv\LiveTvManager.cs" /> + <Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" /> <Compile Include="Localization\LocalizationManager.cs" /> <Compile Include="MediaEncoder\MediaEncoder.cs" /> <Compile Include="Persistence\SqliteChapterRepository.cs" /> |
