aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Channels
diff options
context:
space:
mode:
author7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
committer7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
commit66ad1699e22029b605e17735e8d9450285d8748a (patch)
treeffc92c88d24850b2f82b6b3a8bdd904a2ccc77a5 /MediaBrowser.Server.Implementations/Channels
parent34bc54263e886aae777a3537dc50a6535b51330a (diff)
parent9d36f518182bc075c19d78084870f5115fa62d1e (diff)
Merge pull request #1 from MediaBrowser/master
Update to latest
Diffstat (limited to 'MediaBrowser.Server.Implementations/Channels')
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs29
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs48
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs159
-rw-r--r--MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs2
4 files changed, 188 insertions, 50 deletions
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
new file mode 100644
index 0000000000..9dfb0404e0
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Channels
+{
+ public static class ChannelConfigurationExtension
+ {
+ public static ChannelOptions GetChannelsConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<ChannelOptions>("channels");
+ }
+ }
+
+ public class ChannelConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "channels",
+ ConfigurationType = typeof (ChannelOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
index ce5c41f890..39f747e0a5 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
@@ -71,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Channels
var startingPercent = numComplete * percentPerUser * 100;
var innerProgress = new ActionableProgress<double>();
- innerProgress.RegisterAction(p => progress.Report(startingPercent + (.8 * p)));
+ innerProgress.RegisterAction(p => progress.Report(startingPercent + (percentPerUser * p)));
await DownloadContent(user, cancellationToken, innerProgress).ConfigureAwait(false);
@@ -146,13 +147,15 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var numComplete = 0;
+ var options = _config.GetChannelsConfiguration();
+
foreach (var item in result.Items)
{
- if (_config.Configuration.ChannelOptions.DownloadingChannels.Contains(item.ChannelId))
+ if (options.DownloadingChannels.Contains(item.ChannelId))
{
try
{
- await DownloadChannelItem(item, cancellationToken, path);
+ await DownloadChannelItem(item, options, cancellationToken, path);
}
catch (OperationCanceledException)
{
@@ -174,9 +177,18 @@ namespace MediaBrowser.Server.Implementations.Channels
}
private async Task DownloadChannelItem(BaseItemDto item,
+ ChannelOptions channelOptions,
CancellationToken cancellationToken,
string path)
{
+ if (channelOptions.DownloadSizeLimit.HasValue)
+ {
+ if (IsSizeLimitReached(path, channelOptions.DownloadSizeLimit.Value))
+ {
+ return;
+ }
+ }
+
var sources = await _manager.GetChannelItemMediaSources(item.Id, cancellationToken)
.ConfigureAwait(false);
@@ -218,7 +230,8 @@ namespace MediaBrowser.Server.Implementations.Channels
if (item.IsVideo && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
{
var extension = response.ContentType.Split('/')
- .Last();
+ .Last()
+ .Replace("quicktime", "mov", StringComparison.OrdinalIgnoreCase);
destination += "." + extension;
}
@@ -237,7 +250,7 @@ namespace MediaBrowser.Server.Implementations.Channels
throw new ApplicationException("Unexpected response type encountered: " + response.ContentType);
}
- File.Move(response.TempFilePath, destination);
+ File.Copy(response.TempFilePath, destination, true);
await RefreshMediaSourceItem(destination, cancellationToken).ConfigureAwait(false);
@@ -251,6 +264,25 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
+ private bool IsSizeLimitReached(string path, double gbLimit)
+ {
+ var byteLimit = gbLimit*1000000000;
+
+ long total = 0;
+
+ foreach (var file in new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories))
+ {
+ total += file.Length;
+
+ if (total >= byteLimit)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, CancellationToken cancellationToken)
{
foreach (var item in items)
@@ -282,12 +314,14 @@ namespace MediaBrowser.Server.Implementations.Channels
private void CleanChannelContent(CancellationToken cancellationToken)
{
- if (!_config.Configuration.ChannelOptions.MaxDownloadAge.HasValue)
+ var options = _config.GetChannelsConfiguration();
+
+ if (!options.MaxDownloadAge.HasValue)
{
return;
}
- var minDateModified = DateTime.UtcNow.AddDays(0 - _config.Configuration.ChannelOptions.MaxDownloadAge.Value);
+ var minDateModified = DateTime.UtcNow.AddDays(0 - options.MaxDownloadAge.Value);
var path = _manager.ChannelDownloadPath;
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 188a26c604..c7ca6bb30c 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -1,5 +1,4 @@
-using System.Collections.Concurrent;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -16,6 +15,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -28,7 +28,6 @@ namespace MediaBrowser.Server.Implementations.Channels
{
private IChannel[] _channels;
private IChannelFactory[] _factories;
- private List<Channel> _channelEntities = new List<Channel>();
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
@@ -63,13 +62,13 @@ namespace MediaBrowser.Server.Implementations.Channels
{
get
{
- return TimeSpan.FromDays(1);
+ return TimeSpan.FromHours(12);
}
}
public void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories)
{
- _channels = channels.ToArray();
+ _channels = channels.Where(i => !(i is IFactoryChannel)).ToArray();
_factories = factories.ToArray();
}
@@ -77,9 +76,11 @@ namespace MediaBrowser.Server.Implementations.Channels
{
get
{
- if (!string.IsNullOrWhiteSpace(_config.Configuration.ChannelOptions.DownloadPath))
+ var options = _config.GetChannelsConfiguration();
+
+ if (!string.IsNullOrWhiteSpace(options.DownloadPath))
{
- return _config.Configuration.ChannelOptions.DownloadPath;
+ return options.DownloadPath;
}
return Path.Combine(_config.ApplicationPaths.ProgramDataPath, "channels");
@@ -105,13 +106,16 @@ namespace MediaBrowser.Server.Implementations.Channels
.OrderBy(i => i.Name);
}
- public Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
+ public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrWhiteSpace(query.UserId)
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channelEntities.OrderBy(i => i.SortName).ToList();
+ var channels = GetAllChannels()
+ .Select(GetChannelEntity)
+ .OrderBy(i => i.SortName)
+ .ToList();
if (query.SupportsLatestItems.HasValue)
{
@@ -144,29 +148,46 @@ namespace MediaBrowser.Server.Implementations.Channels
all = all.Take(query.Limit.Value).ToList();
}
+ var returnItems = all.ToArray();
+
+ var result = new QueryResult<Channel>
+ {
+ Items = returnItems,
+ TotalRecordCount = totalCount
+ };
+
+ return Task.FromResult(result);
+ }
+
+ public async Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
+ {
+ var user = string.IsNullOrWhiteSpace(query.UserId)
+ ? null
+ : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false);
+
// Get everything
var fields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
.ToList();
- var returnItems = all.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
{
Items = returnItems,
- TotalRecordCount = totalCount
+ TotalRecordCount = internalResult.TotalRecordCount
};
- return Task.FromResult(result);
+ return result;
}
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
{
var allChannelsList = GetAllChannels().ToList();
- var list = new List<Channel>();
-
var numComplete = 0;
foreach (var channelInfo in allChannelsList)
@@ -177,8 +198,6 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var item = await GetChannel(channelInfo, cancellationToken).ConfigureAwait(false);
- list.Add(item);
-
_libraryManager.RegisterItem(item);
}
catch (OperationCanceledException)
@@ -197,16 +216,28 @@ namespace MediaBrowser.Server.Implementations.Channels
progress.Report(100 * percent);
}
- _channelEntities = list.ToList();
progress.Report(100);
}
+ private Channel GetChannelEntity(IChannel channel)
+ {
+ var item = GetChannel(GetInternalChannelId(channel.Name).ToString("N"));
+
+ if (item == null)
+ {
+ item = GetChannel(channel, CancellationToken.None).Result;
+
+ _libraryManager.RegisterItem(item);
+ }
+
+ return item;
+ }
+
public async Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken)
{
var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
- var channelGuid = new Guid(item.ChannelId);
- var channel = _channelEntities.First(i => i.Id == channelGuid);
+ var channel = GetChannel(item.ChannelId);
var channelPlugin = GetChannelProvider(channel);
var requiresCallback = channelPlugin as IRequiresMediaInfoCallback;
@@ -374,17 +405,23 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var list = channelMediaSources.ToList();
- var width = _config.Configuration.ChannelOptions.PreferredStreamingWidth;
+ var options = _config.GetChannelsConfiguration();
+
+ var width = options.PreferredStreamingWidth;
if (width.HasValue)
{
var val = width.Value;
- return list
- .OrderBy(i => i.Width.HasValue && i.Width.Value <= val)
- .ThenBy(i => Math.Abs(i.Width ?? 0 - val))
+ var res = list
+ .OrderBy(i => (i.Width.HasValue && i.Width.Value <= val ? 0 : 1))
+ .ThenBy(i => Math.Abs((i.Width ?? 0) - val))
.ThenByDescending(i => i.Width ?? 0)
- .ThenBy(list.IndexOf);
+ .ThenBy(list.IndexOf)
+ .ToList();
+
+
+ return res;
}
return list
@@ -476,7 +513,8 @@ namespace MediaBrowser.Server.Implementations.Channels
public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
{
- return _channelEntities
+ return GetAllChannels()
+ .Select(GetChannelEntity)
.OrderBy(i => i.SortName)
.Select(i => GetChannelFeatures(i.Id.ToString("N")));
}
@@ -529,7 +567,12 @@ namespace MediaBrowser.Server.Implementations.Channels
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channels;
+ if (!string.IsNullOrWhiteSpace(query.UserId) && user == null)
+ {
+ throw new ArgumentException("User not found.");
+ }
+
+ var channels = GetAllChannels();
if (query.ChannelIds.Length > 0)
{
@@ -590,8 +633,8 @@ namespace MediaBrowser.Server.Implementations.Channels
var itemTasks = items.Select(i =>
{
var channelProvider = i.Item1;
- var channel = GetChannel(GetInternalChannelId(channelProvider.Name).ToString("N"));
- return GetChannelItemEntity(i.Item2, channelProvider, channel, token);
+ var internalChannelId = GetInternalChannelId(channelProvider.Name);
+ return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token);
});
var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
@@ -683,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.Channels
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channels;
+ var channels = GetAllChannels();
if (query.ChannelIds.Length > 0)
{
@@ -748,8 +791,8 @@ namespace MediaBrowser.Server.Implementations.Channels
var itemTasks = items.Select(i =>
{
var channelProvider = i.Item1;
- var channel = GetChannel(GetInternalChannelId(channelProvider.Name).ToString("N"));
- return GetChannelItemEntity(i.Item2, channelProvider, channel, token);
+ var internalChannelId = GetInternalChannelId(channelProvider.Name);
+ return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token);
});
var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
@@ -822,11 +865,10 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
- public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, CancellationToken cancellationToken)
{
- var queryChannelId = query.ChannelId;
// Get the internal channel entity
- var channel = _channelEntities.First(i => i.Id == new Guid(queryChannelId));
+ var channel = GetChannel(query.ChannelId);
// Find the corresponding channel provider plugin
var channelProvider = GetChannelProvider(channel);
@@ -845,6 +887,12 @@ namespace MediaBrowser.Server.Implementations.Channels
throw new ArgumentException(string.Format("{0} channel only supports a maximum of {1} records at a time.", channel.Name, channelInfo.MaxPageSize.Value));
}
providerLimit = query.Limit;
+
+ // This will cause some providers to fail
+ if (providerLimit == 0)
+ {
+ providerLimit = 1;
+ }
}
var user = string.IsNullOrWhiteSpace(query.UserId)
@@ -873,7 +921,7 @@ namespace MediaBrowser.Server.Implementations.Channels
var providerTotalRecordCount = providerLimit.HasValue ? itemsResult.TotalRecordCount : null;
- var tasks = itemsResult.Items.Select(i => GetChannelItemEntity(i, channelProvider, channel, cancellationToken));
+ var tasks = itemsResult.Items.Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, cancellationToken));
var internalItems = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -890,6 +938,31 @@ namespace MediaBrowser.Server.Implementations.Channels
return await GetReturnItems(internalItems, providerTotalRecordCount, user, query, cancellationToken).ConfigureAwait(false);
}
+ public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ var user = string.IsNullOrWhiteSpace(query.UserId)
+ ? null
+ : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetChannelItemsInternal(query, cancellationToken).ConfigureAwait(false);
+
+ // Get everything
+ var fields = Enum.GetNames(typeof(ItemFields))
+ .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
+ .ToList();
+
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ .ToArray();
+
+ var result = new QueryResult<BaseItemDto>
+ {
+ Items = returnItems,
+ TotalRecordCount = internalResult.TotalRecordCount
+ };
+
+ return result;
+ }
+
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private async Task<ChannelItemResult> GetChannelItems(IChannel channel,
User user,
@@ -1031,7 +1104,7 @@ namespace MediaBrowser.Server.Implementations.Channels
filename + ".json");
}
- private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<BaseItem> items, int? totalCountFromProvider, User user, ChannelItemQuery query, CancellationToken cancellationToken)
+ private async Task<QueryResult<BaseItem>> GetReturnItems(IEnumerable<BaseItem> items, int? totalCountFromProvider, User user, ChannelItemQuery query, CancellationToken cancellationToken)
{
items = ApplyFilters(items, query.Filters, user);
@@ -1055,10 +1128,9 @@ namespace MediaBrowser.Server.Implementations.Channels
await RefreshIfNeeded(all, cancellationToken).ConfigureAwait(false);
- var returnItemArray = all.Select(i => _dtoService.GetBaseItemDto(i, query.Fields, user))
- .ToArray();
+ var returnItemArray = all.ToArray();
- return new QueryResult<BaseItemDto>
+ return new QueryResult<BaseItem>
{
Items = returnItemArray,
TotalRecordCount = totalCount
@@ -1073,7 +1145,7 @@ namespace MediaBrowser.Server.Implementations.Channels
(channelProvider.Name ?? string.Empty) + "16";
}
- private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Channel internalChannel, CancellationToken cancellationToken)
+ private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, CancellationToken cancellationToken)
{
BaseItem item;
Guid id;
@@ -1129,6 +1201,8 @@ namespace MediaBrowser.Server.Implementations.Channels
item.CommunityRating = info.CommunityRating;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
+ item.IndexNumber = info.IndexNumber;
+ item.ParentIndexNumber = info.ParentIndexNumber;
item.People = info.People;
item.PremiereDate = info.PremiereDate;
item.ProductionYear = info.ProductionYear;
@@ -1143,7 +1217,7 @@ namespace MediaBrowser.Server.Implementations.Channels
channelItem.OriginalImageUrl = info.ImageUrl;
channelItem.ExternalId = info.Id;
- channelItem.ChannelId = internalChannel.Id.ToString("N");
+ channelItem.ChannelId = internalChannelId.ToString("N");
channelItem.ChannelItemType = info.Type;
if (isNew)
@@ -1155,13 +1229,14 @@ namespace MediaBrowser.Server.Implementations.Channels
if (channelMediaItem != null)
{
- channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
channelMediaItem.ChannelMediaSources = info.MediaSources;
var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path;
+
+ item.DisplayMediaType = channelMediaItem.ContentType.ToString();
}
if (isNew)
diff --git a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
index ee75e4d050..c6ecfc250f 100644
--- a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
return new ITaskTrigger[]
{
- new StartupTrigger(),
+ new StartupTrigger{DelayMs = 10000},
new SystemEventTrigger{ SystemEvent = SystemEvent.WakeFromSleep},