Add more channel features

This commit is contained in:
Luke Pulverenti 2014-03-18 13:05:57 -04:00
parent cd934c5d3d
commit 4d1d2bbaa1
21 changed files with 317 additions and 34 deletions

View File

@ -18,6 +18,21 @@ namespace MediaBrowser.Api
public int? Limit { get; set; }
}
[Route("/Channels/{Id}/Items", "GET")]
[Api(("Gets channel items"))]
public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>
{
public string Id { get; set; }
public string CategoryId { get; set; }
public string UserId { get; set; }
public int? StartIndex { get; set; }
public int? Limit { get; set; }
}
public class ChannelService : BaseApiService
{
private readonly IChannelManager _channelManager;
@ -39,5 +54,20 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result);
}
public object Get(GetChannelItems request)
{
var result = _channelManager.GetChannelItems(new ChannelItemQuery
{
Limit = request.Limit,
StartIndex = request.StartIndex,
UserId = request.UserId,
ChannelId = request.Id,
CategoryId = request.CategoryId
}, CancellationToken.None).Result;
return ToOptimizedResult(result);
}
}
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@ -6,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@ -242,18 +244,20 @@ namespace MediaBrowser.Api.Library
private readonly IUserDataManager _userDataManager;
private readonly IDtoService _dtoService;
private readonly IChannelManager _channelManager;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
IDtoService dtoService, IUserDataManager userDataManager)
IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
_userManager = userManager;
_dtoService = dtoService;
_userDataManager = userDataManager;
_channelManager = channelManager;
}
public object Get(GetMediaFolders request)
@ -417,6 +421,21 @@ namespace MediaBrowser.Api.Library
var songs = filteredItems.OfType<Audio>().ToList();
var series = filteredItems.OfType<Series>().ToList();
var channelCount = 0;
try
{
channelCount = _channelManager.GetChannels(new ChannelQuery
{
UserId = request.UserId.HasValue ? request.UserId.Value.ToString("N") : null
}, CancellationToken.None).Result.TotalRecordCount;
}
catch (Exception ex)
{
Logger.ErrorException("Error getting channels", ex);
}
var counts = new ItemCounts
{
AlbumCount = albums.Count,
@ -432,7 +451,9 @@ namespace MediaBrowser.Api.Library
BoxSetCount = boxsets.Count,
BookCount = books.Count,
UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList()
UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList(),
ChannelCount = channelCount
};
return ToOptimizedSerializedResultUsingCache(counts);

View File

@ -113,7 +113,7 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string NameStartsWith { get; set; }
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string NameLessThan { get; set; }
@ -240,7 +240,7 @@ namespace MediaBrowser.Api.UserLibrary
public bool? HasOfficialRating { get; set; }
[ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool CollapseBoxSetItems { get; set; }
public bool? CollapseBoxSetItems { get; set; }
}
/// <summary>
@ -318,7 +318,7 @@ namespace MediaBrowser.Api.UserLibrary
items = items.AsEnumerable();
if (request.CollapseBoxSetItems && AllowBoxSetCollapsing(request))
if (CollapseBoxSetItems(request))
{
items = CollapseItemsWithinBoxSets(items, user);
}
@ -346,6 +346,22 @@ namespace MediaBrowser.Api.UserLibrary
};
}
private bool CollapseBoxSetItems(GetItems request)
{
var param = request.CollapseBoxSetItems;
if (!param.HasValue)
{
if (!string.IsNullOrWhiteSpace(request.IncludeItemTypes) &&
request.IncludeItemTypes.Split(',').Contains("Movie", StringComparer.OrdinalIgnoreCase))
{
param = true;
}
}
return param.HasValue && param.Value && AllowBoxSetCollapsing(request);
}
/// <summary>
/// Gets the items to serialize.
/// </summary>
@ -786,7 +802,7 @@ namespace MediaBrowser.Api.UserLibrary
{
items = items.Where(i => string.Compare(request.NameStartsWith, i.SortName.Substring(0, 1), StringComparison.CurrentCultureIgnoreCase) == 0);
}
if (!string.IsNullOrEmpty(request.NameLessThan))
{
items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);

View File

@ -0,0 +1,8 @@
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Channels
{
public class ChannelCategoryItem : Folder
{
}
}

View File

@ -34,7 +34,10 @@ namespace MediaBrowser.Controller.Channels
public ChannelMediaContentType ContentType { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public DateTime? PremiereDate { get; set; }
public int? ProductionYear { get; set; }
public ChannelItemInfo()
{
Genres = new List<string>();

View File

@ -1,4 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -44,19 +47,24 @@ namespace MediaBrowser.Controller.Channels
/// <summary>
/// Gets the channel items.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelItem}}.</returns>
Task<IEnumerable<ChannelItemInfo>> GetChannelItems(User user, CancellationToken cancellationToken);
Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel items.
/// Gets the channel image.
/// </summary>
/// <param name="categoryId">The category identifier.</param>
/// <param name="user">The user.</param>
/// <param name="type">The type.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelItem}}.</returns>
Task<IEnumerable<ChannelItemInfo>> GetChannelItems(string categoryId, User user, CancellationToken cancellationToken);
/// <returns>Task{DynamicImageInfo}.</returns>
Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken);
/// <summary>
/// Gets the supported channel images.
/// </summary>
/// <returns>IEnumerable{ImageType}.</returns>
IEnumerable<ImageType> GetSupportedChannelImages();
}
public class ChannelCapabilities
@ -68,4 +76,18 @@ namespace MediaBrowser.Controller.Channels
{
public string SearchTerm { get; set; }
}
public class InternalChannelItemQuery
{
public string CategoryId { get; set; }
public User User { get; set; }
}
public class ChannelItemResult
{
public List<ChannelItemInfo> Items { get; set; }
public TimeSpan CacheLength { get; set; }
}
}

View File

@ -68,6 +68,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Channels\ChannelCategoryItem.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\IChannel.cs" />
<Compile Include="Channels\IChannelManager.cs" />

View File

@ -219,6 +219,11 @@ namespace MediaBrowser.Dlna
Containers = new[]{"avi"},
MimeType = "avi",
Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
Containers = new[]{"mp4"},
Type = DlnaProfileType.Video
}
}
});
@ -300,6 +305,12 @@ namespace MediaBrowser.Dlna
Containers = new[]{"avi"},
Type = DlnaProfileType.Video,
MimeType = "avi"
},
new DirectPlayProfile
{
Containers = new[]{"asf"},
Type = DlnaProfileType.Audio,
MimeType = "x-ms-wmv"
}
}
});

View File

@ -32,6 +32,14 @@ namespace MediaBrowser.Dlna.PlayTo
{
contentFeatures = "DLNA.ORG_PN=WMABASE";
}
else if (string.Equals(item.FileFormat, "wmw", StringComparison.OrdinalIgnoreCase))
{
contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
}
else if (string.Equals(item.FileFormat, "asf", StringComparison.OrdinalIgnoreCase))
{
contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
}
else if (string.Equals(item.FileFormat, "avi", StringComparison.OrdinalIgnoreCase))
{
contentFeatures = "DLNA.ORG_PN=AVI";

View File

@ -68,7 +68,8 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value>The unique types.</value>
public List<string> UniqueTypes { get; set; }
public int ChannelCount { get; set; }
public ItemCounts()
{
UniqueTypes = new List<string>();

View File

@ -0,0 +1,56 @@
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Channels
{
public class ChannelImageProvider : IDynamicImageProvider, IHasChangeMonitor
{
private readonly IChannelManager _channelManager;
public ChannelImageProvider(IChannelManager channelManager)
{
_channelManager = channelManager;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return GetChannel(item).GetSupportedChannelImages();
}
public Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken)
{
var channel = GetChannel(item);
return channel.GetChannelImage(type, cancellationToken);
}
public string Name
{
get { return "Channel Image Provider"; }
}
public bool Supports(IHasImages item)
{
return item is Channel;
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
return GetSupportedImages(item).Any(i => !item.HasImage(i));
}
private IChannel GetChannel(IHasImages item)
{
var channel = (Channel)item;
return ((ChannelManager)_channelManager).GetChannelProvider(channel);
}
}
}

View File

@ -68,11 +68,6 @@ namespace MediaBrowser.Server.Implementations.Channels
return item is IChannelItem;
}
public int Order
{
get { return 0; }
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
var channelItem = item as IChannelItem;

View File

@ -202,16 +202,19 @@ namespace MediaBrowser.Server.Implementations.Channels
return await GetReturnItems(items, user, query.StartIndex, query.Limit, cancellationToken).ConfigureAwait(false);
}
private Task<IEnumerable<ChannelItemInfo>> GetChannelItems(IChannel channel, User user, string categoryId, CancellationToken cancellationToken)
private async Task<IEnumerable<ChannelItemInfo>> GetChannelItems(IChannel channel, User user, string categoryId, CancellationToken cancellationToken)
{
// TODO: Put some caching in here
if (string.IsNullOrWhiteSpace(categoryId))
var query = new InternalChannelItemQuery
{
return channel.GetChannelItems(user, cancellationToken);
}
User = user,
CategoryId = categoryId
};
return channel.GetChannelItems(categoryId, user, cancellationToken);
var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
return result.Items;
}
private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<ChannelItemInfo> items, User user, int? startIndex, int? limit, CancellationToken cancellationToken)
@ -246,10 +249,36 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info)
{
return null;
BaseItem item;
if (info.Type == ChannelItemType.Category)
{
item = new ChannelCategoryItem();
}
else if (info.MediaType == ChannelMediaType.Audio)
{
item = new ChannelAudioItem();
}
else
{
item = new ChannelVideoItem();
}
item.Name = info.Name;
item.Genres = info.Genres;
item.CommunityRating = info.CommunityRating;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
item.People = info.People;
item.PremiereDate = info.PremiereDate;
item.ProductionYear = info.ProductionYear;
item.RunTimeTicks = info.RunTimeTicks;
item.ProviderIds = info.ProviderIds;
return item;
}
private IChannel GetChannelProvider(Channel channel)
internal IChannel GetChannelProvider(Channel channel)
{
return _channels.First(i => string.Equals(i.Name, channel.OriginalChannelName, StringComparison.OrdinalIgnoreCase));
}

View File

@ -0,0 +1,63 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Model.Tasks;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Channels
{
class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
{
private readonly IChannelManager _manager;
public RefreshChannelsScheduledTask(IChannelManager manager)
{
_manager = manager;
}
public string Name
{
get { return "Refresh Channels"; }
}
public string Description
{
get { return "Refreshes internet channel information."; }
}
public string Category
{
get { return "Channels"; }
}
public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
{
var manager = (ChannelManager)_manager;
return manager.RefreshChannels(progress, cancellationToken);
}
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
{
return new ITaskTrigger[]
{
new StartupTrigger(),
new SystemEventTrigger{ SystemEvent = SystemEvent.WakeFromSleep},
new IntervalTrigger{ Interval = TimeSpan.FromHours(24)}
};
}
public bool IsHidden
{
get { return true; }
}
public bool IsEnabled
{
get { return true; }
}
}
}

View File

@ -106,8 +106,10 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" />
<Compile Include="Channels\ChannelItemImageProvider.cs" />
<Compile Include="Channels\ChannelManager.cs" />
<Compile Include="Channels\RefreshChannelsScheduledTask.cs" />
<Compile Include="Collections\CollectionManager.cs" />
<Compile Include="Collections\CollectionsDynamicFolder.cs" />
<Compile Include="Configuration\ServerConfigurationManager.cs" />

View File

@ -171,6 +171,7 @@ namespace MediaBrowser.ServerApplication
private ILocalizationManager LocalizationManager { get; set; }
private IEncodingManager EncodingManager { get; set; }
private IChannelManager ChannelManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
@ -491,8 +492,8 @@ namespace MediaBrowser.ServerApplication
MediaEncoder);
RegisterSingleInstance(EncodingManager);
var channelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance<IChannelManager>(channelManager);
ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance(ChannelManager);
var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
RegisterSingleInstance<IAppThemeManager>(appThemeManager);
@ -684,6 +685,8 @@ namespace MediaBrowser.ServerApplication
LiveTvManager.AddParts(GetExports<ILiveTvService>());
SessionManager.AddParts(GetExports<ISessionControllerFactory>());
ChannelManager.AddParts(GetExports<IChannel>());
}
/// <summary>

View File

@ -479,6 +479,8 @@ namespace MediaBrowser.WebDashboard.Api
"appsweather.js",
"autoorganizetv.js",
"autoorganizelog.js",
"channels.js",
"channelitems.js",
"dashboardinfo.js",
"dashboardpage.js",
"directorybrowser.js",

View File

@ -93,6 +93,12 @@
<Content Include="dashboard-ui\appsplayback.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\channelitems.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\channels.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\chromecast.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -480,6 +486,12 @@
<Content Include="dashboard-ui\scripts\appsplayback.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\channelitems.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\channels.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\chromecast.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.341</version>
<version>3.0.343</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.341" />
<dependency id="MediaBrowser.Common" version="3.0.343" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.4.1" />
<dependency id="sharpcompress" version="0.10.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.341</version>
<version>3.0.343</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.341</version>
<version>3.0.343</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.341" />
<dependency id="MediaBrowser.Common" version="3.0.343" />
</dependencies>
</metadata>
<files>