mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-22 08:45:23 +03:00
support channels with dlna
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user