diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 5cae4c3f7f..df85ca3cbc 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -626,7 +626,7 @@ namespace MediaBrowser.Api.Playback
/// The state.
/// The output video codec.
/// System.String.
- protected string GetInternalGraphicalSubtitleParam(StreamState state, string outputVideoCodec)
+ protected string GetGraphicalSubtitleParam(StreamState state, string outputVideoCodec)
{
var outputSizeParam = string.Empty;
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index fc1c627e94..ccaa918ec7 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -522,7 +522,7 @@ namespace MediaBrowser.Api.Playback.Hls
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 28c0219fce..1dffa54114 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -186,7 +186,7 @@ namespace MediaBrowser.Api.Playback.Hls
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index bedacc0d29..cdaa99130b 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -167,7 +167,7 @@ namespace MediaBrowser.Api.Playback.Progressive
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
index 38b6b4ad68..78f60632fa 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
@@ -94,7 +94,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
public bool IsHidden
{
- get { return false; }
+ get { return true; }
}
public bool IsEnabled
diff --git a/MediaBrowser.Common/Net/IServerManager.cs b/MediaBrowser.Common/Net/IServerManager.cs
index f6ac0ab68a..84e5785799 100644
--- a/MediaBrowser.Common/Net/IServerManager.cs
+++ b/MediaBrowser.Common/Net/IServerManager.cs
@@ -10,12 +10,6 @@ namespace MediaBrowser.Common.Net
///
public interface IServerManager : IDisposable
{
- ///
- /// Gets the web socket port number.
- ///
- /// The web socket port number.
- int WebSocketPortNumber { get; }
-
///
/// Starts this instance.
///
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index 744eab96e0..252e2aee53 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -43,6 +43,14 @@ namespace MediaBrowser.Controller.Channels
/// Channel.
Channel GetChannel(string id);
+ ///
+ /// Gets the channels internal.
+ ///
+ /// The query.
+ /// The cancellation token.
+ /// Task<QueryResult<Channel>>.
+ Task> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken);
+
///
/// Gets the channels.
///
@@ -75,6 +83,14 @@ namespace MediaBrowser.Controller.Channels
/// Task{QueryResult{BaseItemDto}}.
Task> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
+ ///
+ /// Gets the channel items internal.
+ ///
+ /// The query.
+ /// The cancellation token.
+ /// Task<QueryResult<BaseItem>>.
+ Task> GetChannelItemsInternal(ChannelItemQuery query, CancellationToken cancellationToken);
+
///
/// Gets the cached channel item media sources.
///
diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
index e1383923f6..fa2b49a60b 100644
--- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs
+++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities
public virtual string CollectionType
{
- get { return Model.Entities.CollectionType.BoxSets; }
+ get { return null; }
}
}
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 619a497f5f..be426d99eb 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities;
+using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -29,6 +30,10 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.Trailers:
return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
.OfType();
+ case CollectionType.Movies:
+ return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
+ .Where(i => i is Movie || i is BoxSet)
+ .DistinctBy(i => i.Id);
default:
return mediaFolders.SelectMany(i => i.GetChildren(user, includeLinkedChildren));
}
@@ -70,4 +75,30 @@ namespace MediaBrowser.Controller.Entities
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
}
}
+
+ public class SpecialFolder : Folder
+ {
+ public SpecialFolderType SpecialFolderType { get; set; }
+ public string ItemTypeName { get; set; }
+ public string ParentId { get; set; }
+
+ public override IEnumerable GetChildren(User user, bool includeLinkedChildren)
+ {
+ var parent = (Folder)LibraryManager.GetItemById(new Guid(ParentId));
+
+ if (SpecialFolderType == SpecialFolderType.ItemsByType)
+ {
+ var items = parent.GetRecursiveChildren(user, includeLinkedChildren);
+
+ return items.Where(i => string.Equals(i.GetType().Name, ItemTypeName, StringComparison.OrdinalIgnoreCase));
+ }
+
+ return new List();
+ }
+ }
+
+ public enum SpecialFolderType
+ {
+ ItemsByType = 1
+ }
}
diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs
index 86699272e8..6ef1fb6f72 100644
--- a/MediaBrowser.Controller/Library/TVUtils.cs
+++ b/MediaBrowser.Controller/Library/TVUtils.cs
@@ -8,6 +8,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
+using MediaBrowser.Model.Logging;
namespace MediaBrowser.Controller.Library
{
@@ -136,6 +137,16 @@ namespace MediaBrowser.Controller.Library
return val;
}
+ if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase))
+ {
+ var testFilename = filename.Substring(1);
+
+ if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
+ {
+ return val;
+ }
+ }
+
// Look for one of the season folder names
foreach (var name in SeasonFolderNames)
{
@@ -182,7 +193,7 @@ namespace MediaBrowser.Controller.Library
return null;
}
- return int.Parse(path.Substring(numericStart, length));
+ return int.Parse(path.Substring(numericStart, length), CultureInfo.InvariantCulture);
}
///
@@ -194,21 +205,59 @@ namespace MediaBrowser.Controller.Library
/// true if [is season folder] [the specified path]; otherwise, false.
private static bool IsSeasonFolder(string path, IDirectoryService directoryService, IFileSystem fileSystem)
{
+ var seasonNumber = GetSeasonNumberFromPath(path);
+ var hasSeasonNumber = seasonNumber != null;
+
+ if (!hasSeasonNumber)
+ {
+ return false;
+ }
+
// It's a season folder if it's named as such and does not contain any audio files, apart from theme.mp3
- return GetSeasonNumberFromPath(path) != null &&
- !directoryService.GetFiles(path)
- .Any(i => EntityResolutionHelper.IsAudioFile(i.FullName) && !string.Equals(fileSystem.GetFileNameWithoutExtension(i), BaseItem.ThemeSongFilename));
+ foreach (var fileSystemInfo in directoryService.GetFileSystemEntries(path))
+ {
+ var attributes = fileSystemInfo.Attributes;
+
+ if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ {
+ continue;
+ }
+
+ if ((attributes & FileAttributes.System) == FileAttributes.System)
+ {
+ continue;
+ }
+
+ if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ //if (IsBadFolder(fileSystemInfo.Name))
+ //{
+ // return false;
+ //}
+ }
+ else
+ {
+ if (EntityResolutionHelper.IsAudioFile(fileSystemInfo.FullName) &&
+ !string.Equals(fileSystem.GetFileNameWithoutExtension(fileSystemInfo), BaseItem.ThemeSongFilename))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
///
/// Determines whether [is series folder] [the specified path].
///
/// The path.
- /// if set to true [consider seasonless series].
+ /// if set to true [consider seasonless entries].
/// The file system children.
/// The directory service.
+ /// The file system.
/// true if [is series folder] [the specified path]; otherwise, false.
- public static bool IsSeriesFolder(string path, bool considerSeasonlessSeries, IEnumerable fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem)
+ public static bool IsSeriesFolder(string path, bool considerSeasonlessEntries, IEnumerable fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem, ILogger logger)
{
// A folder with more than 3 non-season folders in will not becounted as a series
var nonSeriesFolders = 0;
@@ -231,15 +280,20 @@ namespace MediaBrowser.Controller.Library
{
if (IsSeasonFolder(child.FullName, directoryService, fileSystem))
{
+ logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
return true;
}
- if (!EntityResolutionHelper.IgnoreFolders.Contains(child.Name, StringComparer.OrdinalIgnoreCase))
+
+ if (IsBadFolder(child.Name))
{
+ logger.Debug("Invalid folder under series: {0}", child.FullName);
+
nonSeriesFolders++;
}
if (nonSeriesFolders >= 3)
{
+ logger.Debug("{0} not a series due to 3 or more invalid folders.", path);
return false;
}
}
@@ -249,7 +303,7 @@ namespace MediaBrowser.Controller.Library
if (EntityResolutionHelper.IsVideoFile(fullName) || EntityResolutionHelper.IsVideoPlaceHolder(fullName))
{
- if (GetEpisodeNumberFromFile(fullName, considerSeasonlessSeries).HasValue)
+ if (GetEpisodeNumberFromFile(fullName, considerSeasonlessEntries).HasValue)
{
return true;
}
@@ -257,9 +311,28 @@ namespace MediaBrowser.Controller.Library
}
}
+ logger.Debug("{0} is not a series folder.", path);
return false;
}
+ private static bool IsBadFolder(string name)
+ {
+ if (string.Equals(name, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(name, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ return !EntityResolutionHelper.IgnoreFolders.Contains(name, StringComparer.OrdinalIgnoreCase);
+ }
+
///
/// Episodes the number from file.
///
diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
index cc5cb1b1a2..78db68f63f 100644
--- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
+++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
@@ -45,7 +45,7 @@ namespace MediaBrowser.Dlna.Channels
_localServersLookup = localServersLookup;
_deviceDiscovery = deviceDiscovery;
- deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
+ //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
}
@@ -196,25 +196,16 @@ namespace MediaBrowser.Dlna.Channels
public class ServerChannel : IChannel, IFactoryChannel
{
- private readonly List _servers = new List();
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
- private readonly string _controlUrl;
+ public string ControlUrl { get; set; }
+ public List Servers { get; set; }
- ///
- /// Prevents core from throwing an exception
- ///
- public ServerChannel()
+ public ServerChannel(IHttpClient httpClient, ILogger logger)
{
-
- }
-
- public ServerChannel(List servers, IHttpClient httpClient, ILogger logger, string controlUrl)
- {
- _servers = servers;
_httpClient = httpClient;
_logger = logger;
- _controlUrl = controlUrl;
+ Servers = new List();
}
public string Name
@@ -272,7 +263,7 @@ namespace MediaBrowser.Dlna.Channels
if (string.IsNullOrWhiteSpace(query.FolderId))
{
- items = _servers.Select(i => new ChannelItemInfo
+ items = Servers.Select(i => new ChannelItemInfo
{
FolderType = ChannelFolderType.Container,
Id = GetServerId(i),
@@ -291,7 +282,7 @@ namespace MediaBrowser.Dlna.Channels
Limit = query.Limit,
StartIndex = query.StartIndex,
ParentId = folderId,
- ContentDirectoryUrl = _controlUrl
+ ContentDirectoryUrl = ControlUrl
}, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
index f594b4471d..f5731b8938 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -21,6 +22,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly IDlnaManager _dlna;
private readonly IServerConfigurationManager _config;
private readonly IUserManager _userManager;
+ private readonly IUserViewManager _userViewManager;
+ private readonly IChannelManager _channelManager;
public ContentDirectory(IDlnaManager dlna,
IUserDataManager userDataManager,
@@ -29,7 +32,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
- IHttpClient httpClient)
+ IHttpClient httpClient, IUserViewManager userViewManager, IChannelManager channelManager)
: base(logger, httpClient)
{
_dlna = dlna;
@@ -38,6 +41,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
_libraryManager = libraryManager;
_config = config;
_userManager = userManager;
+ _userViewManager = userViewManager;
+ _channelManager = channelManager;
}
private int SystemUpdateId
@@ -73,7 +78,9 @@ namespace MediaBrowser.Dlna.ContentDirectory
_userDataManager,
user,
SystemUpdateId,
- _config)
+ _config,
+ _userViewManager,
+ _channelManager)
.ProcessControlRequest(request);
}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
index b4f918e68b..1553435aeb 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
@@ -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> HandleBrowse(Headers sparams, User user, string deviceId)
+ private async Task>> 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> HandleSearch(Headers sparams, User user, string deviceId)
+ private async Task>> 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 GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort)
+ private async Task> 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 GetChildrenSorted(Folder folder, User user, SortCriteria sort)
+ private async Task> 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 ToResult(IEnumerable 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
+ {
+ Items = list,
+ TotalRecordCount = totalCount
+ };
+ }
+
+ private async Task> GetUserViewChildren(UserView folder, User user, SortCriteria sort)
+ {
+ if (string.Equals(folder.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+ {
+ return new List();
+ }
+ 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(), 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(), user, sort);
+ }
+
+ return GetPlainFolderChildrenSorted(folder, user, sort);
+ }
+
+ private IEnumerable GetPlainFolderChildrenSorted(Folder folder, User user, SortCriteria sort)
{
var items = folder.GetChildren(user, true);
@@ -345,7 +456,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable SortItems(IEnumerable 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 FilterUnsupportedContent(IEnumerable 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;
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index 739793c032..649ba2c8ff 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -612,6 +613,13 @@ namespace MediaBrowser.Dlna.Didl
{
return GetImageInfo(item, ImageType.Thumb);
}
+ if (item.HasImage(ImageType.Backdrop))
+ {
+ if (item is Channel)
+ {
+ return GetImageInfo(item, ImageType.Backdrop);
+ }
+ }
if (item is Audio || item is Episode)
{
@@ -633,7 +641,7 @@ namespace MediaBrowser.Dlna.Didl
try
{
- tag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
+ tag = _imageProcessor.GetImageCacheTag(item, type);
}
catch
{
diff --git a/MediaBrowser.Dlna/Images/logo120.jpg b/MediaBrowser.Dlna/Images/logo120.jpg
index 1de803c8fa..394c8e1376 100644
Binary files a/MediaBrowser.Dlna/Images/logo120.jpg and b/MediaBrowser.Dlna/Images/logo120.jpg differ
diff --git a/MediaBrowser.Dlna/Images/logo120.png b/MediaBrowser.Dlna/Images/logo120.png
index 2dd04d4681..97bdef818b 100644
Binary files a/MediaBrowser.Dlna/Images/logo120.png and b/MediaBrowser.Dlna/Images/logo120.png differ
diff --git a/MediaBrowser.Dlna/Images/logo240.jpg b/MediaBrowser.Dlna/Images/logo240.jpg
new file mode 100644
index 0000000000..c805523516
Binary files /dev/null and b/MediaBrowser.Dlna/Images/logo240.jpg differ
diff --git a/MediaBrowser.Dlna/Images/logo240.png b/MediaBrowser.Dlna/Images/logo240.png
new file mode 100644
index 0000000000..532f123178
Binary files /dev/null and b/MediaBrowser.Dlna/Images/logo240.png differ
diff --git a/MediaBrowser.Dlna/Images/logo48.jpg b/MediaBrowser.Dlna/Images/logo48.jpg
index f1e7302aae..52b9853541 100644
Binary files a/MediaBrowser.Dlna/Images/logo48.jpg and b/MediaBrowser.Dlna/Images/logo48.jpg differ
diff --git a/MediaBrowser.Dlna/Images/logo48.png b/MediaBrowser.Dlna/Images/logo48.png
index 3b13d141ce..29d4a05289 100644
Binary files a/MediaBrowser.Dlna/Images/logo48.png and b/MediaBrowser.Dlna/Images/logo48.png differ
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index 461470b7ac..962c2a211e 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -184,6 +184,10 @@
+
+
+
+