support channels with dlna

This commit is contained in:
Luke Pulverenti
2014-07-29 23:31:35 -04:00
parent 063675bb07
commit 51e964dae3
93 changed files with 957 additions and 326 deletions

View File

@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
@@ -9,8 +10,10 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Dlna.Didl;
using MediaBrowser.Dlna.Server;
using MediaBrowser.Dlna.Service;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using System;
@@ -19,6 +22,7 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
namespace MediaBrowser.Dlna.ContentDirectory
@@ -40,14 +44,18 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly DidlBuilder _didlBuilder;
private readonly DeviceProfile _profile;
private readonly IUserViewManager _userViewManager;
private readonly IChannelManager _channelManager;
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config)
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, IUserViewManager userViewManager, IChannelManager channelManager)
: base(config, logger)
{
_libraryManager = libraryManager;
_userDataManager = userDataManager;
_user = user;
_systemUpdateId = systemUpdateId;
_userViewManager = userViewManager;
_channelManager = channelManager;
_profile = profile;
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress);
@@ -69,7 +77,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return HandleGetSystemUpdateID();
if (string.Equals(methodName, "Browse", StringComparison.OrdinalIgnoreCase))
return HandleBrowse(methodParams, user, deviceId);
return HandleBrowse(methodParams, user, deviceId).Result;
if (string.Equals(methodName, "X_GetFeatureList", StringComparison.OrdinalIgnoreCase))
return HandleXGetFeatureList();
@@ -78,7 +86,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return HandleXSetBookmark(methodParams, user);
if (string.Equals(methodName, "Search", StringComparison.OrdinalIgnoreCase))
return HandleSearch(methodParams, user, deviceId);
return HandleSearch(methodParams, user, deviceId).Result;
throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
}
@@ -141,7 +149,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return builder.ToString();
}
private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams, User user, string deviceId)
private async Task<IEnumerable<KeyValuePair<string, string>>> HandleBrowse(Headers sparams, User user, string deviceId)
{
var id = sparams["ObjectID"];
var flag = sparams["BrowseFlag"];
@@ -149,16 +157,20 @@ namespace MediaBrowser.Dlna.ContentDirectory
var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
var provided = 0;
var requested = 0;
var start = 0;
if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
int? requested = 0;
int? start = 0;
int requestedVal;
if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
{
requested = 0;
requested = requestedVal;
}
if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out start) && start <= 0)
int startVal;
if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
{
start = 0;
start = startVal;
}
//var root = GetItem(id) as IMediaFolder;
@@ -173,34 +185,26 @@ namespace MediaBrowser.Dlna.ContentDirectory
var folder = (Folder)GetItemFromObjectId(id, user);
var children = GetChildrenSorted(folder, user, sortCriteria).ToList();
var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
var totalCount = children.Count;
var totalCount = childrenResult.TotalRecordCount;
if (string.Equals(flag, "BrowseMetadata"))
{
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, children.Count, filter));
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter));
provided++;
}
else
{
if (start > 0)
{
children = children.Skip(start).ToList();
}
if (requested > 0)
{
children = children.Take(requested).ToList();
}
provided = childrenResult.Items.Length;
provided = children.Count;
foreach (var i in children)
foreach (var i in childrenResult.Items)
{
if (i.IsFolder)
{
var f = (Folder)i;
var childCount = GetChildrenSorted(f, user, sortCriteria).Count();
var childCount = (await GetChildrenSorted(f, user, sortCriteria, null, 0).ConfigureAwait(false))
.TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
}
@@ -222,7 +226,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
};
}
private IEnumerable<KeyValuePair<string, string>> HandleSearch(Headers sparams, User user, string deviceId)
private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
{
var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
@@ -230,16 +234,19 @@ namespace MediaBrowser.Dlna.ContentDirectory
// sort example: dc:title, dc:date
var requested = 0;
var start = 0;
int? requested = 0;
int? start = 0;
if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
int requestedVal;
if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
{
requested = 0;
requested = requestedVal;
}
if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out start) && start <= 0)
int startVal;
if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
{
start = 0;
start = startVal;
}
//var root = GetItem(id) as IMediaFolder;
@@ -259,27 +266,19 @@ namespace MediaBrowser.Dlna.ContentDirectory
var folder = (Folder)GetItemFromObjectId(sparams["ContainerID"], user);
var children = GetChildrenSorted(folder, user, searchCriteria, sortCriteria).ToList();
var childrenResult = (await GetChildrenSorted(folder, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
var totalCount = children.Count;
var totalCount = childrenResult.TotalRecordCount;
if (start > 0)
{
children = children.Skip(start).ToList();
}
if (requested > 0)
{
children = children.Take(requested).ToList();
}
var provided = childrenResult.Items.Length;
var provided = children.Count;
foreach (var i in children)
foreach (var i in childrenResult.Items)
{
if (i.IsFolder)
{
var f = (Folder)i;
var childCount = GetChildrenSorted(f, user, searchCriteria, sortCriteria).Count();
var childCount = (await GetChildrenSorted(f, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
.TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
}
@@ -300,15 +299,16 @@ namespace MediaBrowser.Dlna.ContentDirectory
};
}
private IEnumerable<BaseItem> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort)
private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
{
if (search.SearchType == SearchType.Unknown)
{
return GetChildrenSorted(folder, user, sort);
return await GetChildrenSorted(folder, user, sort, startIndex, limit).ConfigureAwait(false);
}
var items = folder.GetRecursiveChildren(user);
items = FilterUnsupportedContent(items);
var result = await GetChildrenSorted(folder, user, sort, null, null).ConfigureAwait(false);
var items = FilterUnsupportedContent(result.Items);
if (search.SearchType == SearchType.Audio)
{
@@ -324,12 +324,123 @@ namespace MediaBrowser.Dlna.ContentDirectory
}
else if (search.SearchType == SearchType.Playlist)
{
}
return SortItems(items, user, sort);
items = SortItems(items, user, sort);
return ToResult(items, startIndex, limit);
}
private IEnumerable<BaseItem> GetChildrenSorted(Folder folder, User user, SortCriteria sort)
private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SortCriteria sort, int? startIndex, int? limit)
{
if (folder is UserRootFolder)
{
var result = await _userViewManager.GetUserViews(new UserViewQuery
{
UserId = user.Id.ToString("N")
}, CancellationToken.None).ConfigureAwait(false);
return ToResult(result, startIndex, limit);
}
var view = folder as UserView;
if (view != null)
{
var result = await GetUserViewChildren(view, user, sort).ConfigureAwait(false);
return ToResult(result, startIndex, limit);
}
var channel = folder as Channel;
if (channel != null)
{
return await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
{
ChannelId = channel.Id.ToString("N"),
Limit = limit,
StartIndex = startIndex,
UserId = user.Id.ToString("N")
}, CancellationToken.None);
}
var channelFolderItem = folder as ChannelFolderItem;
if (channelFolderItem != null)
{
return await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
{
ChannelId = channelFolderItem.ChannelId,
FolderId = channelFolderItem.Id.ToString("N"),
Limit = limit,
StartIndex = startIndex,
UserId = user.Id.ToString("N")
}, CancellationToken.None);
}
return ToResult(GetPlainFolderChildrenSorted(folder, user, sort), startIndex, limit);
}
private QueryResult<BaseItem> ToResult(IEnumerable<BaseItem> items, int? startIndex, int? limit)
{
var list = items.ToArray();
var totalCount = list.Length;
if (startIndex.HasValue)
{
list = list.Skip(startIndex.Value).ToArray();
}
if (limit.HasValue)
{
list = list.Take(limit.Value).ToArray();
}
return new QueryResult<BaseItem>
{
Items = list,
TotalRecordCount = totalCount
};
}
private async Task<IEnumerable<BaseItem>> GetUserViewChildren(UserView folder, User user, SortCriteria sort)
{
if (string.Equals(folder.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
return new List<BaseItem>();
}
if (string.Equals(folder.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
{
var result = await _channelManager.GetChannelsInternal(new ChannelQuery()
{
UserId = user.Id.ToString("N")
}, CancellationToken.None).ConfigureAwait(false);
return result.Items;
}
if (string.Equals(folder.ViewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
return SortItems(folder.GetChildren(user, true).OfType<Series>(), user, sort);
}
if (string.Equals(folder.ViewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
return GetPlainFolderChildrenSorted(folder, user, sort);
}
if (string.Equals(folder.ViewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
{
return SortItems(folder.GetChildren(user, true).OfType<MusicArtist>(), user, sort);
}
return GetPlainFolderChildrenSorted(folder, user, sort);
}
private IEnumerable<BaseItem> GetPlainFolderChildrenSorted(Folder folder, User user, SortCriteria sort)
{
var items = folder.GetChildren(user, true);
@@ -345,7 +456,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable<BaseItem> SortItems(IEnumerable<BaseItem> items, User user, SortCriteria sort)
{
return _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
return _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, sort.SortOrder);
}
private IEnumerable<BaseItem> FilterUnsupportedContent(IEnumerable<BaseItem> items)
@@ -353,14 +464,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
return items.Where(i =>
{
// Unplayable
// TODO: Display and prevent playback with restricted flag?
if (i.LocationType == LocationType.Virtual)
{
return false;
}
// Unplayable
// TODO: Display and prevent playback with restricted flag?
var supportsPlaceHolder = i as ISupportsPlaceHolders;
if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
{
@@ -368,7 +477,6 @@ namespace MediaBrowser.Dlna.ContentDirectory
}
// Upnp renderers won't understand these
// TODO: Display and prevent playback with restricted flag?
if (i is Game || i is Book)
{
return false;