aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs6
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj2
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs27
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs1
-rw-r--r--MediaBrowser.Api/TvShowsService.cs136
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj2
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj2
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs30
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs30
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs4
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs30
-rw-r--r--MediaBrowser.Controller/Entities/UserItemsQuery.cs35
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs13
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs80
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs614
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs9
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj5
-rw-r--r--MediaBrowser.Controller/TV/ITVSeriesManager.cs24
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs11
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs249
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs52
-rw-r--r--MediaBrowser.Dlna/Main/DlnaEntryPoint.cs9
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs6
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToManager.cs7
-rw-r--r--MediaBrowser.Dlna/Ssdp/Datagram.cs14
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs16
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj2
-rw-r--r--MediaBrowser.Model/Entities/CollectionType.cs21
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj2
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj2
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs14
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs23
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json18
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj5
-rw-r--r--MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs202
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs15
-rw-r--r--MediaBrowser.ServerApplication/LibraryViewer.cs76
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs2
-rw-r--r--MediaBrowser.ServerApplication/ServerNotifyIcon.cs8
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj2
44 files changed, 1329 insertions, 485 deletions
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 2213a5af1..2aa680061 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -39,8 +39,8 @@ namespace MediaBrowser.Api.Images
[Route("/Items/{Id}/Images/{Type}", "GET")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "GET")]
- [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "GET")]
- [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "HEAD")]
+ [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "GET")]
+ [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "HEAD")]
[Api(Description = "Gets an item image")]
public class GetItemImage : ImageRequest
{
@@ -583,7 +583,7 @@ namespace MediaBrowser.Api.Images
Width = request.Width,
OutputFormat = request.Format,
AddPlayedIndicator = request.AddPlayedIndicator,
- PercentPlayed = request.PercentPlayed,
+ PercentPlayed = request.PercentPlayed ?? 0,
UnplayedCount = request.UnplayedCount,
BackgroundColor = request.BackgroundColor
};
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 5cb9ebb1b..b0131b5c2 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -169,7 +169,7 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 31a81de73..19f9db636 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1516,6 +1516,7 @@ namespace MediaBrowser.Api.Playback
state.RunTimeTicks = item.RunTimeTicks;
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
state.InputBitrate = mediaSource.Bitrate;
+ state.InputFileSize = mediaSource.Size;
mediaStreams = mediaSource.MediaStreams;
}
else
@@ -1530,6 +1531,7 @@ namespace MediaBrowser.Api.Playback
state.MediaPath = mediaSource.Path;
state.InputProtocol = mediaSource.Protocol;
state.InputContainer = mediaSource.Container;
+ state.InputFileSize = mediaSource.Size;
state.InputBitrate = mediaSource.Bitrate;
if (item is Video)
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 997cc7ca4..f0ad6ce5c 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using System.Linq;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -153,7 +154,25 @@ namespace MediaBrowser.Api.Playback.Progressive
using (state)
{
- var throttleLimit = state.InputBitrate.HasValue ? (state.InputBitrate.Value / 8) : 0;
+ var limits = new List<long>();
+ if (state.InputBitrate.HasValue)
+ {
+ // Bytes per second
+ limits.Add((state.InputBitrate.Value / 8));
+ }
+ if (state.InputFileSize.HasValue && state.RunTimeTicks.HasValue)
+ {
+ var totalSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds;
+
+ if (totalSeconds > 1)
+ {
+ var timeBasedLimit = state.InputFileSize.Value / totalSeconds;
+ limits.Add(Convert.ToInt64(timeBasedLimit));
+ }
+ }
+
+ // Take the greater of the above to methods, just to be safe
+ var throttleLimit = limits.Count > 0 ? limits.Max() : 0;
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
{
@@ -166,8 +185,8 @@ namespace MediaBrowser.Api.Playback.Progressive
// Pad by 20% to play it safe
ThrottleLimit = Convert.ToInt64(1.2 * throttleLimit),
- // Three minutes
- MinThrottlePosition = throttleLimit * 180
+ // 3.5 minutes
+ MinThrottlePosition = throttleLimit * 210
});
}
}
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 139a78c80..d6933b755 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -69,6 +69,7 @@ namespace MediaBrowser.Api.Playback
public long? RunTimeTicks;
public long? InputBitrate { get; set; }
+ public long? InputFileSize { get; set; }
public string OutputAudioSync = "1";
public string OutputVideoSync = "vfr";
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index c32e67216..20a3d3837 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack;
@@ -26,7 +27,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The user id.</value>
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
+ public string UserId { get; set; }
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
@@ -195,6 +196,7 @@ namespace MediaBrowser.Api
private readonly IItemRepository _itemRepo;
private readonly IDtoService _dtoService;
+ private readonly ITVSeriesManager _tvSeriesManager;
/// <summary>
/// Initializes a new instance of the <see cref="TvShowsService" /> class.
@@ -202,13 +204,14 @@ namespace MediaBrowser.Api
/// <param name="userManager">The user manager.</param>
/// <param name="userDataManager">The user data repository.</param>
/// <param name="libraryManager">The library manager.</param>
- public TvShowsService(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
+ public TvShowsService(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, ITVSeriesManager tvSeriesManager)
{
_userManager = userManager;
_userDataManager = userDataManager;
_libraryManager = libraryManager;
_itemRepo = itemRepo;
_dtoService = dtoService;
+ _tvSeriesManager = tvSeriesManager;
}
/// <summary>
@@ -270,129 +273,26 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public object Get(GetNextUpEpisodes request)
{
- var user = _userManager.GetUserById(request.UserId);
-
- var itemsList = GetNextUpEpisodes(request)
- .ToList();
+ var result = _tvSeriesManager.GetNextUp(new NextUpQuery
+ {
+ Limit = request.Limit,
+ ParentId = request.ParentId,
+ SeriesId = request.SeriesId,
+ StartIndex = request.StartIndex,
+ UserId = request.UserId
+ });
- var pagedItems = ApplyPaging(itemsList, request.StartIndex, request.Limit);
+ var user = _userManager.GetUserById(new Guid(request.UserId));
var fields = request.GetItemFields().ToList();
- var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray();
+ var returnItems = result.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray();
- var result = new ItemsResult
+ return ToOptimizedSerializedResultUsingCache(new ItemsResult
{
- TotalRecordCount = itemsList.Count,
+ TotalRecordCount = result.TotalRecordCount,
Items = returnItems
- };
-
- return ToOptimizedSerializedResultUsingCache(result);
- }
-
- public IEnumerable<Episode> GetNextUpEpisodes(GetNextUpEpisodes request)
- {
- var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId)
- .OfType<Series>();
-
- // Avoid implicitly captured closure
- return GetNextUpEpisodes(request, items);
- }
-
- public IEnumerable<Episode> GetNextUpEpisodes(GetNextUpEpisodes request, IEnumerable<Series> series)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- // Avoid implicitly captured closure
- var currentUser = user;
-
- return FilterSeries(request, series)
- .AsParallel()
- .Select(i => GetNextUp(i, currentUser))
- .Where(i => i.Item1 != null)
- .OrderByDescending(i =>
- {
- var episode = i.Item1;
-
- var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey());
-
- if (seriesUserData.IsFavorite)
- {
- return 2;
- }
-
- if (seriesUserData.Likes.HasValue)
- {
- return seriesUserData.Likes.Value ? 1 : -1;
- }
-
- return 0;
- })
- .ThenByDescending(i => i.Item2)
- .ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
- .Select(i => i.Item1);
- }
-
- /// <summary>
- /// Gets the next up.
- /// </summary>
- /// <param name="series">The series.</param>
- /// <param name="user">The user.</param>
- /// <returns>Task{Episode}.</returns>
- private Tuple<Episode, DateTime> GetNextUp(Series series, User user)
- {
- // Get them in display order, then reverse
- var allEpisodes = series.GetSeasons(user, true, true)
- .SelectMany(i => i.GetEpisodes(user, true, true))
- .Reverse()
- .ToList();
-
- Episode lastWatched = null;
- var lastWatchedDate = DateTime.MinValue;
- Episode nextUp = null;
-
- // Go back starting with the most recent episodes
- foreach (var episode in allEpisodes)
- {
- var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey());
-
- if (userData.Played)
- {
- if (lastWatched != null || nextUp == null)
- {
- break;
- }
-
- lastWatched = episode;
- lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue;
- }
- else
- {
- if (episode.LocationType != LocationType.Virtual)
- {
- nextUp = episode;
- }
- }
- }
-
- if (lastWatched != null)
- {
- return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate);
- }
-
- return new Tuple<Episode, DateTime>(null, lastWatchedDate);
- }
-
- private IEnumerable<Series> FilterSeries(GetNextUpEpisodes request, IEnumerable<Series> items)
- {
- if (!string.IsNullOrWhiteSpace(request.SeriesId))
- {
- var id = new Guid(request.SeriesId);
-
- items = items.Where(i => i.Id == id);
- }
-
- return items;
+ });
}
/// <summary>
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index 4b0c95616..74c812226 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -122,7 +122,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<PropertyGroup>
<PostBuildEvent Condition=" '$(ConfigurationName)' != 'Release Mono' ">if '$(ConfigurationName)' == 'Release' (
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 661073c89..fd41c7e9e 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -116,7 +116,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<PropertyGroup>
<PostBuildEvent Condition=" '$(ConfigurationName)' != 'Release Mono' ">if '$(ConfigurationName)' == 'Release' (
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index df38259b4..602918b19 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -1,6 +1,10 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Querying;
using System;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Channels
{
@@ -17,5 +21,31 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
+
+ public override async Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
+ {
+ try
+ {
+ // Don't blow up here because it could cause parent screens with other content to fail
+ return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = Id.ToString("N"),
+ Limit = query.Limit,
+ StartIndex = query.StartIndex,
+ UserId = query.User.Id.ToString("N"),
+ SortBy = query.SortBy,
+ SortOrder = query.SortOrder
+
+ }, CancellationToken.None);
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return new QueryResult<BaseItem>
+ {
+
+ };
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index 077138f3c..a7cc80104 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -1,6 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Querying;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Channels
{
@@ -33,5 +36,32 @@ namespace MediaBrowser.Controller.Channels
{
return ExternalId;
}
+
+ public override async Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
+ {
+ try
+ {
+ // Don't blow up here because it could cause parent screens with other content to fail
+ return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = ChannelId,
+ FolderId = Id.ToString("N"),
+ Limit = query.Limit,
+ StartIndex = query.StartIndex,
+ UserId = query.User.Id.ToString("N"),
+ SortBy = query.SortBy,
+ SortOrder = query.SortOrder
+
+ }, CancellationToken.None);
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return new QueryResult<BaseItem>
+ {
+
+ };
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 7a261bc58..10e486e71 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -11,8 +11,6 @@ namespace MediaBrowser.Controller.Channels
{
public class ChannelVideoItem : Video, IChannelMediaItem
{
- public static IChannelManager ChannelManager { get; set; }
-
public string ExternalId { get; set; }
public string ChannelId { get; set; }
diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
index f4a76be00..fbbf21797 100644
--- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Drawing
public int? UnplayedCount { get; set; }
- public double? PercentPlayed { get; set; }
+ public double PercentPlayed { get; set; }
public string BackgroundColor { get; set; }
@@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Drawing
return (!Quality.HasValue || Quality.Value == 100) &&
IsOutputFormatDefault(originalImagePath) &&
!AddPlayedIndicator &&
- !PercentPlayed.HasValue &&
+ PercentPlayed.Equals(0) &&
!UnplayedCount.HasValue &&
string.IsNullOrEmpty(BackgroundColor);
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 26b28ec72..3830fa1c1 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
@@ -240,6 +241,7 @@ namespace MediaBrowser.Controller.Entities
public static IFileSystem FileSystem { get; set; }
public static IUserDataManager UserDataManager { get; set; }
public static ILiveTvManager LiveTvManager { get; set; }
+ public static IChannelManager ChannelManager { get; set; }
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 356f2b603..3907217be 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -6,6 +6,8 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+using MoreLinq;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -14,7 +16,6 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using MoreLinq;
namespace MediaBrowser.Controller.Entities
{
@@ -24,6 +25,7 @@ namespace MediaBrowser.Controller.Entities
public class Folder : BaseItem, IHasThemeMedia, IHasTags
{
public static IUserManager UserManager { get; set; }
+ public static IUserViewManager UserViewManager { get; set; }
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
@@ -770,6 +772,24 @@ namespace MediaBrowser.Controller.Entities
return item;
}
+ public virtual Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
+ {
+ var user = query.User;
+
+ var items = query.Recursive
+ ? GetRecursiveChildren(user)
+ : GetChildren(user, true);
+
+ var result = SortAndFilter(items, query);
+
+ return Task.FromResult(result);
+ }
+
+ protected QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, UserItemsQuery query)
+ {
+ return UserViewBuilder.SortAndFilter(items, null, query, LibraryManager, UserDataManager);
+ }
+
/// <summary>
/// Gets allowed children of an item
/// </summary>
@@ -944,7 +964,7 @@ namespace MediaBrowser.Controller.Entities
.OfType<CollectionFolder>()
.SelectMany(i => i.PhysicalLocations)
.ToList();
-
+
return LinkedChildren
.Select(i =>
{
@@ -985,10 +1005,10 @@ namespace MediaBrowser.Controller.Entities
/// Gets the linked children.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
- public IEnumerable<Tuple<LinkedChild,BaseItem>> GetLinkedChildrenInfos()
+ public IEnumerable<Tuple<LinkedChild, BaseItem>> GetLinkedChildrenInfos()
{
return LinkedChildren
- .Select(i => new Tuple<LinkedChild,BaseItem>(i, GetLinkedChild(i)))
+ .Select(i => new Tuple<LinkedChild, BaseItem>(i, GetLinkedChild(i)))
.Where(i => i.Item2 != null);
}
@@ -1183,7 +1203,7 @@ namespace MediaBrowser.Controller.Entities
var isUnplayed = true;
var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
-
+
// Incrememt totalPercentPlayed
if (itemUserData != null)
{
diff --git a/MediaBrowser.Controller/Entities/UserItemsQuery.cs b/MediaBrowser.Controller/Entities/UserItemsQuery.cs
new file mode 100644
index 000000000..ca1c0115d
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/UserItemsQuery.cs
@@ -0,0 +1,35 @@
+using MediaBrowser.Model.Entities;
+using System;
+
+namespace MediaBrowser.Controller.Entities
+{
+ public class UserItemsQuery
+ {
+ public bool Recursive { get; set; }
+
+ public int? StartIndex { get; set; }
+
+ public int? Limit { get; set; }
+
+ public string[] SortBy { get; set; }
+
+ public SortOrder SortOrder { get; set; }
+
+ public User User { get; set; }
+
+ public Func<BaseItem, User, bool> Filter { get; set; }
+
+ public bool? IsFolder { get; set; }
+ public bool? IsFavorite { get; set; }
+ public bool? IsPlayed { get; set; }
+ public bool? IsResumable { get; set; }
+
+ public string[] MediaTypes { get; set; }
+
+ public UserItemsQuery()
+ {
+ SortBy = new string[] { };
+ MediaTypes = new string[] { };
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index 6404e71ec..5c7cb7e23 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Library;
+using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -14,6 +16,17 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserRootFolder : Folder
{
+ public override async Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
+ {
+ var result = await UserViewManager.GetUserViews(new UserViewQuery
+ {
+ UserId = query.User.Id.ToString("N")
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return SortAndFilter(result, query);
+ }
+
/// <summary>
/// Get the children of this folder from the actual file system
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 2abc71752..9b26ce23c 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -1,12 +1,9 @@
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
@@ -14,56 +11,37 @@ namespace MediaBrowser.Controller.Entities
public class UserView : Folder
{
public string ViewType { get; set; }
- public static IUserViewManager UserViewManager { get; set; }
+ public Guid ParentId { get; set; }
- public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+ public static ITVSeriesManager TVSeriesManager;
+
+ public override Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
{
- var mediaFolders = GetMediaFolders(user);
+ return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager)
+ .GetUserItems(this, ViewType, query);
+ }
- switch (ViewType)
+ public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+ {
+ var result = GetUserItems(new UserItemsQuery
{
- case CollectionType.LiveTvChannels:
- return LiveTvManager.GetInternalChannels(new LiveTvChannelQuery
- {
- UserId = user.Id.ToString("N")
-
- }, CancellationToken.None).Result.Items;
- case CollectionType.LiveTvRecordingGroups:
- return LiveTvManager.GetInternalRecordings(new RecordingQuery
- {
- UserId = user.Id.ToString("N"),
- Status = RecordingStatus.Completed
-
- }, CancellationToken.None).Result.Items;
- case CollectionType.LiveTv:
- return GetLiveTvFolders(user).Result;
- case CollectionType.Folders:
- return user.RootFolder.GetChildren(user, includeLinkedChildren);
- case CollectionType.Games:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
- .OfType<GameSystem>();
- case CollectionType.BoxSets:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
- .OfType<BoxSet>();
- case CollectionType.TvShows:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
- .OfType<Series>();
- case CollectionType.Trailers:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
- .OfType<Trailer>();
- default:
- return mediaFolders.SelectMany(i => i.GetChildren(user, includeLinkedChildren));
- }
+ User = user
+
+ }).Result;
+
+ return result.Items;
}
- private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user)
+ public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
- var list = new List<BaseItem>();
+ var result = GetUserItems(new UserItemsQuery
+ {
+ User = user,
+ Recursive = true
- list.Add(await UserViewManager.GetUserView(CollectionType.LiveTvChannels, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
- list.Add(await UserViewManager.GetUserView(CollectionType.LiveTvRecordingGroups, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
+ }).Result;
- return list;
+ return result.Items;
}
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
@@ -71,16 +49,6 @@ namespace MediaBrowser.Controller.Entities
return GetChildren(user, false);
}
- private IEnumerable<Folder> GetMediaFolders(User user)
- {
- var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
-
- return user.RootFolder
- .GetChildren(user, true, true)
- .OfType<Folder>()
- .Where(i => !excludeFolderIds.Contains(i.Id) && !IsExcludedFromGrouping(i));
- }
-
public static bool IsExcludedFromGrouping(Folder folder)
{
var standaloneTypes = new List<string>
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
new file mode 100644
index 000000000..f11ac70ca
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -0,0 +1,614 @@
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.TV;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Entities
+{
+ public class UserViewBuilder
+ {
+ private readonly IChannelManager _channelManager;
+ private readonly ILiveTvManager _liveTvManager;
+ private readonly IUserViewManager _userViewManager;
+ private readonly ILibraryManager _libraryManager;
+ private readonly ILogger _logger;
+ private readonly IUserDataManager _userDataManager;
+ private readonly ITVSeriesManager _tvSeriesManager;
+
+ public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager)
+ {
+ _userViewManager = userViewManager;
+ _liveTvManager = liveTvManager;
+ _channelManager = channelManager;
+ _libraryManager = libraryManager;
+ _logger = logger;
+ _userDataManager = userDataManager;
+ _tvSeriesManager = tvSeriesManager;
+ }
+
+ public async Task<QueryResult<BaseItem>> GetUserItems(Folder parent, string viewType, UserItemsQuery query)
+ {
+ var user = query.User;
+
+ switch (viewType)
+ {
+ case CollectionType.Channels:
+ {
+ var result = await _channelManager.GetChannelsInternal(new ChannelQuery
+ {
+ UserId = user.Id.ToString("N"),
+ Limit = query.Limit,
+ StartIndex = query.StartIndex
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return GetResult(result);
+ }
+
+ case CollectionType.LiveTvChannels:
+ {
+ var result = await _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
+ {
+ UserId = query.User.Id.ToString("N"),
+ Limit = query.Limit,
+ StartIndex = query.StartIndex
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return GetResult(result);
+ }
+
+ case CollectionType.LiveTvNowPlaying:
+ {
+ var result = await _liveTvManager.GetRecommendedProgramsInternal(new RecommendedProgramQuery
+ {
+ UserId = query.User.Id.ToString("N"),
+ Limit = query.Limit,
+ IsAiring = true
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return GetResult(result);
+ }
+
+ case CollectionType.LiveTvRecordingGroups:
+ {
+ var result = await _liveTvManager.GetInternalRecordings(new RecordingQuery
+ {
+ UserId = query.User.Id.ToString("N"),
+ Status = RecordingStatus.Completed,
+ Limit = query.Limit,
+ StartIndex = query.StartIndex
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return GetResult(result);
+ }
+
+ case CollectionType.LiveTv:
+ {
+ var result = await GetLiveTvFolders(user).ConfigureAwait(false);
+
+ return GetResult(result, query);
+ }
+
+ case CollectionType.Folders:
+ return GetResult(user.RootFolder.GetChildren(user, true), query);
+
+ case CollectionType.Games:
+ return await GetGameView(user, parent, query).ConfigureAwait(false);
+
+ case CollectionType.BoxSets:
+ return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), query);
+
+ case CollectionType.TvShows:
+ return await GetTvView(parent, user, query).ConfigureAwait(false);
+
+ case CollectionType.Music:
+ return await GetMusicFolders(parent, user, query).ConfigureAwait(false);
+
+ case CollectionType.Movies:
+ return await GetMovieFolders(parent, user, query).ConfigureAwait(false);
+
+ case CollectionType.GameGenres:
+ return GetGameGenres(parent, user, query);
+
+ case CollectionType.GameSystems:
+ return GetGameSystems(parent, user, query);
+
+ case CollectionType.LatestGames:
+ return GetLatestGames(parent, user, query);
+
+ case CollectionType.RecentlyPlayedGames:
+ return GetRecentlyPlayedGames(parent, user, query);
+
+ case CollectionType.GameFavorites:
+ return GetFavoriteGames(parent, user, query);
+
+ case CollectionType.TvSeries:
+ return GetTvSeries(parent, user, query);
+
+ case CollectionType.TvGenres:
+ return GetTvGenres(parent, user, query);
+
+ case CollectionType.TvResume:
+ return GetTvResume(parent, user, query);
+
+ case CollectionType.TvNextUp:
+ return GetTvNextUp(parent, query);
+
+ case CollectionType.TvLatest:
+ return GetTvLatest(parent, user, query);
+
+ case CollectionType.MovieFavorites:
+ return GetFavoriteMovies(parent, user, query);
+
+ case CollectionType.MovieLatest:
+ return GetMovieLatest(parent, user, query);
+
+ case CollectionType.MovieGenres:
+ return GetMovieGenres(parent, user, query);
+
+ case CollectionType.MovieResume:
+ return GetMovieResume(parent, user, query);
+
+ case CollectionType.MovieMovies:
+ return GetMovieMovies(parent, user, query);
+
+ case CollectionType.MovieCollections:
+ return GetMovieCollections(parent, user, query);
+
+ default:
+ return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), query);
+ }
+ }
+
+ private int GetSpecialItemsLimit()
+ {
+ return 50;
+ }
+
+ private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, UserItemsQuery query)
+ {
+ if (query.Recursive)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }), query);
+ }
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).OfType<MusicArtist>(), query);
+ }
+
+ private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, UserItemsQuery query)
+ {
+ if (query.Recursive)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie || i is BoxSet), query);
+ }
+
+ var list = new List<BaseItem>();
+
+ list.Add(await GetUserView(CollectionType.MovieResume, user, "0", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.MovieLatest, user, "1", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.MovieMovies, user, "2", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.MovieCollections, user, "3", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.MovieFavorites, user, "4", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.MovieGenres, user, "5", parent).ConfigureAwait(false));
+
+ return GetResult(list, query);
+ }
+
+ private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, UserItemsQuery query)
+ {
+ query.IsFavorite = true;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
+ }
+
+ private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, UserItemsQuery query)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
+ }
+
+ private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, UserItemsQuery query)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is BoxSet), query);
+ }
+
+ private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, UserItemsQuery query)
+ {
+ query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, UserItemsQuery query)
+ {
+ query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+ query.IsResumable = true;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, UserItemsQuery query)
+ {
+ var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
+ .Where(i => i is Movie)
+ .SelectMany(i => i.Genres)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .Select(i =>
+ {
+ try
+ {
+ return _libraryManager.GetGenre(i);
+ }
+ catch
+ {
+ // Full exception logged at lower levels
+ _logger.Error("Error getting genre");
+ return null;
+ }
+
+ })
+ .Where(i => i != null);
+
+ return GetResult(genres, query);
+ }
+
+ private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, UserItemsQuery query)
+ {
+ if (query.Recursive)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series || i is Season || i is Episode), query);
+ }
+
+ var list = new List<BaseItem>();
+
+ list.Add(await GetUserView(CollectionType.TvResume, user, "0", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvNextUp, user, "1", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvLatest, user, "2", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvSeries, user, "3", parent).ConfigureAwait(false));
+ //list.Add(await GetUserView(CollectionType.TvFavorites, user, "4", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvGenres, user, "5", parent).ConfigureAwait(false));
+
+ return GetResult(list, query);
+ }
+
+ private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, UserItemsQuery query)
+ {
+ if (query.Recursive)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }), query);
+ }
+
+ var list = new List<BaseItem>();
+
+ list.Add(await GetUserView(CollectionType.LatestGames, user, "0", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.RecentlyPlayedGames, user, "1", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.GameFavorites, user, "2", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.GameSystems, user, "3", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.GameGenres, user, "4", parent).ConfigureAwait(false));
+
+ return GetResult(list, query);
+ }
+
+ private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, UserItemsQuery query)
+ {
+ query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, UserItemsQuery query)
+ {
+ query.IsPlayed = true;
+ query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, UserItemsQuery query)
+ {
+ query.IsFavorite = true;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), query);
+ }
+
+ private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, UserItemsQuery query)
+ {
+ query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetTvNextUp(Folder parent, UserItemsQuery query)
+ {
+ var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty });
+
+ var result = _tvSeriesManager.GetNextUp(new NextUpQuery
+ {
+ Limit = query.Limit,
+ StartIndex = query.StartIndex,
+ UserId = query.User.Id.ToString("N")
+
+ }, parentFolders);
+
+ return result;
+ }
+
+ private QueryResult<BaseItem> GetTvResume(Folder parent, User user, UserItemsQuery query)
+ {
+ query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
+ query.SortOrder = SortOrder.Descending;
+ query.IsResumable = true;
+
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
+ }
+
+ private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, UserItemsQuery query)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), query);
+ }
+
+ private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, UserItemsQuery query)
+ {
+ var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
+ .OfType<Series>()
+ .SelectMany(i => i.Genres)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .Select(i =>
+ {
+ try
+ {
+ return _libraryManager.GetGenre(i);
+ }
+ catch
+ {
+ // Full exception logged at lower levels
+ _logger.Error("Error getting genre");
+ return null;
+ }
+
+ })
+ .Where(i => i != null);
+
+ return GetResult(genres, query);
+ }
+
+ private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, UserItemsQuery query)
+ {
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), query);
+ }
+
+ private QueryResult<BaseItem> GetGameGenres(Folder parent, User user, UserItemsQuery query)
+ {
+ var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
+ .OfType<Game>()
+ .SelectMany(i => i.Genres)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .Select(i =>
+ {
+ try
+ {
+ return _libraryManager.GetGameGenre(i);
+ }
+ catch
+ {
+ // Full exception logged at lower levels
+ _logger.Error("Error getting game genre");
+ return null;
+ }
+
+ })
+ .Where(i => i != null);
+
+ return GetResult(genres, query);
+ }
+
+ private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
+ where T : BaseItem
+ {
+ return new QueryResult<BaseItem>
+ {
+ Items = result.Items,
+ TotalRecordCount = result.TotalRecordCount
+ };
+ }
+
+ private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
+ UserItemsQuery query)
+ where T : BaseItem
+ {
+ return GetResult(items, null, query);
+ }
+
+ private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
+ int? totalRecordLimit,
+ UserItemsQuery query)
+ where T : BaseItem
+ {
+ return SortAndFilter(items, totalRecordLimit, query, _libraryManager, _userDataManager);
+ }
+
+ public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items,
+ int? totalRecordLimit,
+ UserItemsQuery query,
+ ILibraryManager libraryManager,
+ IUserDataManager userDataManager)
+ {
+ var user = query.User;
+
+ items = items.Where(i => Filter(i, user, query, userDataManager));
+
+ return Sort(items, totalRecordLimit, query, libraryManager);
+ }
+
+ public static QueryResult<BaseItem> Sort(IEnumerable<BaseItem> items,
+ int? totalRecordLimit,
+ UserItemsQuery query,
+ ILibraryManager libraryManager)
+ {
+ var user = query.User;
+
+ items = libraryManager.ReplaceVideosWithPrimaryVersions(items);
+
+ if (query.SortBy.Length > 0)
+ {
+ items = libraryManager.Sort(items, user, query.SortBy, query.SortOrder);
+ }
+
+ var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();
+ var totalCount = itemsArray.Length;
+
+ if (query.Limit.HasValue)
+ {
+ itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray();
+ }
+ else if (query.StartIndex.HasValue)
+ {
+ itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
+ }
+
+ return new QueryResult<BaseItem>
+ {
+ TotalRecordCount = totalCount,
+ Items = itemsArray
+ };
+ }
+
+ private static bool Filter(BaseItem item, User user, UserItemsQuery query, IUserDataManager userDataManager)
+ {
+ if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
+ {
+ return false;
+ }
+
+ if (query.Filter != null && !query.Filter(item, user))
+ {
+ return false;
+ }
+
+ UserItemData userData = null;
+
+ if (query.IsFavorite.HasValue)
+ {
+ userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+
+ if (userData.IsFavorite != query.IsFavorite.Value)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsResumable.HasValue)
+ {
+ userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var isResumable = userData.PlaybackPositionTicks > 0;
+
+ if (isResumable != query.IsResumable.Value)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsPlayed.HasValue)
+ {
+ if (item.IsPlayed(user) != query.IsPlayed.Value)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private IEnumerable<Folder> GetMediaFolders(User user)
+ {
+ var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
+
+ return user.RootFolder
+ .GetChildren(user, true, true)
+ .OfType<Folder>()
+ .Where(i => !excludeFolderIds.Contains(i.Id) && !UserView.IsExcludedFromGrouping(i));
+ }
+
+ private IEnumerable<Folder> GetMediaFolders(User user, string[] viewTypes)
+ {
+ return GetMediaFolders(user)
+ .Where(i =>
+ {
+ var folder = i as ICollectionFolder;
+
+ return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ });
+ }
+
+ private IEnumerable<Folder> GetMediaFolders(Folder parent, User user, string[] viewTypes)
+ {
+ if (parent == null || parent is UserView)
+ {
+ return GetMediaFolders(user, viewTypes);
+ }
+
+ return new[] { parent };
+ }
+
+ private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, string[] viewTypes)
+ {
+ if (parent == null || parent is UserView)
+ {
+ return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user));
+ }
+
+ return parent.GetRecursiveChildren(user);
+ }
+
+ private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user)
+ {
+ var list = new List<BaseItem>();
+
+ list.Add(await _userViewManager.GetUserView(CollectionType.LiveTvNowPlaying, user, "0", CancellationToken.None).ConfigureAwait(false));
+ list.Add(await _userViewManager.GetUserView(CollectionType.LiveTvChannels, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
+ list.Add(await _userViewManager.GetUserView(CollectionType.LiveTvRecordingGroups, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
+
+ return list;
+ }
+
+ private async Task<UserView> GetUserView(string type, User user, string sortName, Folder parent)
+ {
+ var view = await _userViewManager.GetUserView(type, user, sortName, CancellationToken.None)
+ .ConfigureAwait(false);
+
+ if (parent.Id != view.ParentId)
+ {
+ view.ParentId = parent.Id;
+ await view.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None)
+ .ConfigureAwait(false);
+ }
+
+ return view;
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index b1c6ebffc..370ac2e75 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -245,6 +245,15 @@ namespace MediaBrowser.Controller.LiveTv
CancellationToken cancellationToken);
/// <summary>
+ /// Gets the recommended programs internal.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;LiveTvProgram&gt;&gt;.</returns>
+ Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query,
+ CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the live tv information.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 6a78fa5d9..2ad950a4f 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -157,7 +157,9 @@
<Compile Include="Entities\IHasAwards.cs" />
<Compile Include="Entities\Photo.cs" />
<Compile Include="Entities\PhotoAlbum.cs" />
+ <Compile Include="Entities\UserItemsQuery.cs" />
<Compile Include="Entities\UserView.cs" />
+ <Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
@@ -336,6 +338,7 @@
<Compile Include="Sync\ISyncRepository.cs" />
<Compile Include="Themes\IAppThemeManager.cs" />
<Compile Include="Themes\InternalThemeImage.cs" />
+ <Compile Include="TV\ITVSeriesManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
@@ -360,7 +363,7 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.Controller/TV/ITVSeriesManager.cs b/MediaBrowser.Controller/TV/ITVSeriesManager.cs
new file mode 100644
index 000000000..3d6e87474
--- /dev/null
+++ b/MediaBrowser.Controller/TV/ITVSeriesManager.cs
@@ -0,0 +1,24 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Querying;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.TV
+{
+ public interface ITVSeriesManager
+ {
+ /// <summary>
+ /// Gets the next up.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
+ QueryResult<BaseItem> GetNextUp(NextUpQuery query);
+
+ /// <summary>
+ /// Gets the next up.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <param name="parentsFolders">The parents folders.</param>
+ /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
+ QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders);
+ }
+}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
index f5731b893..f594b4471 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -22,8 +21,6 @@ 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,
@@ -32,7 +29,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
- IHttpClient httpClient, IUserViewManager userViewManager, IChannelManager channelManager)
+ IHttpClient httpClient)
: base(logger, httpClient)
{
_dlna = dlna;
@@ -41,8 +38,6 @@ namespace MediaBrowser.Dlna.ContentDirectory
_libraryManager = libraryManager;
_config = config;
_userManager = userManager;
- _userViewManager = userViewManager;
- _channelManager = channelManager;
}
private int SystemUpdateId
@@ -78,9 +73,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_userDataManager,
user,
SystemUpdateId,
- _config,
- _userViewManager,
- _channelManager)
+ _config)
.ProcessControlRequest(request);
}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
index 3d08159d6..34acb4479 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
@@ -1,26 +1,18 @@
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Playlists;
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;
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -45,21 +37,17 @@ 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, IUserViewManager userViewManager, IChannelManager channelManager)
+ public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config)
: base(config, logger)
{
_libraryManager = libraryManager;
_userDataManager = userDataManager;
_user = user;
_systemUpdateId = systemUpdateId;
- _userViewManager = userViewManager;
- _channelManager = channelManager;
_profile = profile;
- _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress);
+ _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, userDataManager);
}
protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)
@@ -202,7 +190,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
{
- var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
+ var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
totalCount = childrenResult.TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter, id));
@@ -213,7 +201,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
{
var folder = (Folder)item;
- var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
+ var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
totalCount = childrenResult.TotalRecordCount;
provided = childrenResult.Items.Length;
@@ -223,7 +211,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
if (i.IsFolder)
{
var f = (Folder)i;
- var childCount = (await GetChildrenSorted(f, user, sortCriteria, null, 0).ConfigureAwait(false))
+ var childCount = (await GetUserItems(f, user, sortCriteria, null, 0).ConfigureAwait(false))
.TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
@@ -321,216 +309,97 @@ namespace MediaBrowser.Dlna.ContentDirectory
private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
{
- // TODO: Make a recursive version of GetChildrenSorted (although sorting isn't needed)
- var result = folder.GetRecursiveChildren(user, true);
+ var sortOrders = new List<string>();
+ if (!folder.IsPreSorted)
+ {
+ sortOrders.Add(ItemSortBy.SortName);
+ }
- var items = FilterUnsupportedContent(result);
+ var mediaTypes = new List<string>();
+ bool? isFolder = null;
if (search.SearchType == SearchType.Audio)
{
- items = items.OfType<Audio>();
+ mediaTypes.Add(MediaType.Audio);
+ isFolder = false;
}
else if (search.SearchType == SearchType.Video)
{
- items = items.OfType<Video>();
+ mediaTypes.Add(MediaType.Video);
+ isFolder = false;
}
else if (search.SearchType == SearchType.Image)
{
- items = items.OfType<Photo>();
+ mediaTypes.Add(MediaType.Photo);
+ isFolder = false;
}
else if (search.SearchType == SearchType.Playlist)
{
- items = items.OfType<Playlist>();
+ //items = items.OfType<Playlist>();
+ isFolder = true;
}
else if (search.SearchType == SearchType.MusicAlbum)
{
- items = items.OfType<MusicAlbum>();
+ //items = items.OfType<MusicAlbum>();
+ isFolder = true;
}
-
- items = SortItems(items, user, sort);
-
- return ToResult(items, startIndex, limit);
+
+ return await folder.GetUserItems(new UserItemsQuery
+ {
+ Limit = limit,
+ StartIndex = startIndex,
+ SortBy = sortOrders.ToArray(),
+ SortOrder = sort.SortOrder,
+ User = user,
+ Recursive = true,
+ Filter = FilterUnsupportedContent,
+ IsFolder = isFolder,
+ MediaTypes = mediaTypes.ToArray()
+
+ }).ConfigureAwait(false);
}
- private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SortCriteria sort, int? startIndex, int? limit)
+ private async Task<QueryResult<BaseItem>> GetUserItems(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 sortOrders = new List<string>();
+ if (!folder.IsPreSorted)
{
- var result = await GetUserViewChildren(view, user, sort).ConfigureAwait(false);
-
- return ToResult(result, startIndex, limit);
+ sortOrders.Add(ItemSortBy.SortName);
}
- var channel = folder as Channel;
-
- if (channel != null)
+ return await folder.GetUserItems(new UserItemsQuery
{
- try
- {
- // Don't blow up here because it could cause parent screens with other content to fail
- return await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
- {
- ChannelId = channel.Id.ToString("N"),
- Limit = limit,
- StartIndex = startIndex,
- UserId = user.Id.ToString("N")
-
- }, CancellationToken.None);
- }
- catch
- {
- // Already logged at lower levels
- }
- }
+ Limit = limit,
+ StartIndex = startIndex,
+ SortBy = sortOrders.ToArray(),
+ SortOrder = sort.SortOrder,
+ User = user,
+ Filter = FilterUnsupportedContent
- var channelFolderItem = folder as ChannelFolderItem;
-
- if (channelFolderItem != null)
- {
- try
- {
- // Don't blow up here because it could cause parent screens with other content to fail
- 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);
- }
- catch
- {
- // Already logged at lower levels
- }
- }
-
- return ToResult(GetPlainFolderChildrenSorted(folder, user, sort), startIndex, limit);
+ }).ConfigureAwait(false);
}
- private QueryResult<BaseItem> ToResult(IEnumerable<BaseItem> items, int? startIndex, int? limit)
+ private bool FilterUnsupportedContent(BaseItem i, User user)
{
- var list = items.ToArray();
- var totalCount = list.Length;
-
- if (startIndex.HasValue)
+ // Unplayable
+ if (i.LocationType == LocationType.Virtual && !i.IsFolder)
{
- list = list.Skip(startIndex.Value).ToArray();
+ return false;
}
- if (limit.HasValue)
+ // Unplayable
+ var supportsPlaceHolder = i as ISupportsPlaceHolders;
+ if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
{
- list = list.Take(limit.Value).ToArray();
+ return false;
}
- return new QueryResult<BaseItem>
+ if (i is Game || i is Book)
{
- Items = list,
- TotalRecordCount = totalCount
- };
- }
-
- private async Task<IEnumerable<BaseItem>> GetUserViewChildren(UserView folder, User user, SortCriteria sort)
- {
- 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;
+ //return false;
}
- 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 SortItems(folder.GetRecursiveChildren(user, true).OfType<Movie>(), user, sort);
- }
- if (string.Equals(folder.ViewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
- {
- return SortItems(folder.GetChildren(user, true).OfType<MusicArtist>(), user, sort);
- }
- if (string.Equals(folder.ViewType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase))
- {
- return SortItems(folder.GetChildren(user, true), user, sort);
- }
- if (string.Equals(folder.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
- {
- return SortItems(folder.GetChildren(user, true), user, sort);
- }
- if (string.Equals(folder.ViewType, CollectionType.LiveTvRecordingGroups, StringComparison.OrdinalIgnoreCase))
- {
- return SortItems(folder.GetChildren(user, true), user, sort);
- }
- if (string.Equals(folder.ViewType, CollectionType.LiveTvChannels, StringComparison.OrdinalIgnoreCase))
- {
- return SortItems(folder.GetChildren(user, true), user, sort);
- }
-
- return GetPlainFolderChildrenSorted(folder, user, sort);
- }
-
- private IEnumerable<BaseItem> GetPlainFolderChildrenSorted(Folder folder, User user, SortCriteria sort)
- {
- var items = folder.GetChildren(user, true);
-
- items = FilterUnsupportedContent(items);
-
- if (folder.IsPreSorted)
- {
- return items;
- }
-
- return SortItems(items, user, sort);
- }
-
- private IEnumerable<BaseItem> SortItems(IEnumerable<BaseItem> items, User user, SortCriteria sort)
- {
- return _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, sort.SortOrder);
- }
-
- private IEnumerable<BaseItem> FilterUnsupportedContent(IEnumerable<BaseItem> items)
- {
- return items.Where(i =>
- {
- // Unplayable
- if (i.LocationType == LocationType.Virtual && !i.IsFolder)
- {
- return false;
- }
-
- // Unplayable
- var supportsPlaceHolder = i as ISupportsPlaceHolders;
- if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
- {
- return false;
- }
-
- if (i is Game || i is Book)
- {
- return false;
- }
- return true;
- });
+ return true;
}
private BaseItem GetItemFromObjectId(string id, User user)
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index 53fac9a93..bcfd566a9 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
@@ -6,16 +6,16 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using System;
-using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Xml;
-using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Dlna.Didl
{
@@ -32,12 +32,14 @@ namespace MediaBrowser.Dlna.Didl
private readonly IImageProcessor _imageProcessor;
private readonly string _serverAddress;
private readonly User _user;
+ private readonly IUserDataManager _userDataManager;
- public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress)
+ public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, IUserDataManager userDataManager)
{
_profile = profile;
_imageProcessor = imageProcessor;
_serverAddress = serverAddress;
+ _userDataManager = userDataManager;
_user = user;
}
@@ -677,7 +679,20 @@ namespace MediaBrowser.Dlna.Didl
var result = element.OwnerDocument;
- var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, "jpg");
+ var playbackPercentage = 0;
+
+ if (item is Video)
+ {
+ var userData = _userDataManager.GetUserDataDto(item, _user);
+
+ playbackPercentage = Convert.ToInt32(userData.PlayedPercentage ?? 0);
+ if (playbackPercentage >= 100)
+ {
+ playbackPercentage = 0;
+ }
+ }
+
+ var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, playbackPercentage, "jpg");
var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP);
var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
@@ -687,7 +702,7 @@ namespace MediaBrowser.Dlna.Didl
element.AppendChild(icon);
// TOOD: Remove these default values
- var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
+ var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, playbackPercentage, "jpg");
icon = result.CreateElement("upnp", "icon", NS_UPNP);
icon.InnerText = iconUrlInfo.Url;
element.AppendChild(icon);
@@ -703,18 +718,19 @@ namespace MediaBrowser.Dlna.Didl
}
}
- AddImageResElement(item, element, 4096, 4096, "jpg", "JPEG_LRG");
- AddImageResElement(item, element, 4096, 4096, "png", "PNG_LRG");
- AddImageResElement(item, element, 1024, 768, "jpg", "JPEG_MED");
- AddImageResElement(item, element, 640, 480, "jpg", "JPEG_SM");
- AddImageResElement(item, element, 160, 160, "jpg", "JPEG_TN");
- AddImageResElement(item, element, 160, 160, "png", "PNG_TN");
+ AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG");
+ AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG");
+ AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED");
+ AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM");
+ AddImageResElement(item, element, 160, 160, playbackPercentage, "jpg", "JPEG_TN");
+ AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN");
}
private void AddImageResElement(BaseItem item,
XmlElement element,
int maxWidth,
int maxHeight,
+ int playbackPercentage,
string format,
string org_Pn)
{
@@ -727,7 +743,7 @@ namespace MediaBrowser.Dlna.Didl
var result = element.OwnerDocument;
- var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, format);
+ var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, playbackPercentage, format);
var res = result.CreateElement(string.Empty, "res", NS_DIDL);
@@ -849,16 +865,18 @@ namespace MediaBrowser.Dlna.Didl
internal int? Height;
}
- private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
+ private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, string format)
{
- var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}",
+ var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}",
_serverAddress,
info.ItemId,
info.Type,
info.ImageTag,
format,
- maxWidth,
- maxHeight);
+ maxWidth.ToString(CultureInfo.InvariantCulture),
+ maxHeight.ToString(CultureInfo.InvariantCulture),
+ playbackPercentage.ToString(CultureInfo.InvariantCulture)
+ );
var width = info.Width;
var height = info.Height;
diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
index 8914ae8bf..4d3e2272a 100644
--- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
+++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
@@ -34,14 +34,15 @@ namespace MediaBrowser.Dlna.Main
private readonly IUserManager _userManager;
private readonly IDlnaManager _dlnaManager;
private readonly IImageProcessor _imageProcessor;
-
+ private readonly IUserDataManager _userDataManager;
+
private SsdpHandler _ssdpHandler;
private DeviceDiscovery _deviceDiscovery;
private readonly List<string> _registeredServerIds = new List<string>();
private bool _dlnaServerStarted;
- public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor)
+ public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor, IUserDataManager userDataManager)
{
_config = config;
_appHost = appHost;
@@ -53,6 +54,7 @@ namespace MediaBrowser.Dlna.Main
_userManager = userManager;
_dlnaManager = dlnaManager;
_imageProcessor = imageProcessor;
+ _userDataManager = userDataManager;
_logger = logManager.GetLogger("Dlna");
}
@@ -218,7 +220,8 @@ namespace MediaBrowser.Dlna.Main
_imageProcessor,
_deviceDiscovery,
_httpClient,
- _config);
+ _config,
+ _userDataManager);
_manager.Start();
}
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index 9e8d8213f..acada6a11 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -32,6 +32,7 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly IDlnaManager _dlnaManager;
private readonly IUserManager _userManager;
private readonly IImageProcessor _imageProcessor;
+ private readonly IUserDataManager _userDataManager;
private readonly DeviceDiscovery _deviceDiscovery;
private readonly string _serverAddress;
@@ -51,7 +52,7 @@ namespace MediaBrowser.Dlna.PlayTo
private Timer _updateTimer;
- public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, DeviceDiscovery deviceDiscovery)
+ public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, DeviceDiscovery deviceDiscovery, IUserDataManager userDataManager)
{
_session = session;
_itemRepository = itemRepository;
@@ -62,6 +63,7 @@ namespace MediaBrowser.Dlna.PlayTo
_imageProcessor = imageProcessor;
_serverAddress = serverAddress;
_deviceDiscovery = deviceDiscovery;
+ _userDataManager = userDataManager;
_logger = logger;
}
@@ -474,7 +476,7 @@ namespace MediaBrowser.Dlna.PlayTo
playlistItem.StreamUrl = playlistItem.StreamInfo.ToUrl(serverAddress);
- var itemXml = new DidlBuilder(profile, user, _imageProcessor, serverAddress).GetItemDidl(item, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
+ var itemXml = new DidlBuilder(profile, user, _imageProcessor, serverAddress, _userDataManager).GetItemDidl(item, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
playlistItem.Didl = itemXml;
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
index a52c38086..891dcec87 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
@@ -29,10 +29,11 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly IImageProcessor _imageProcessor;
private readonly IHttpClient _httpClient;
private readonly IServerConfigurationManager _config;
+ private readonly IUserDataManager _userDataManager;
private readonly DeviceDiscovery _deviceDiscovery;
- public PlayToManager(ILogger logger, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config)
+ public PlayToManager(ILogger logger, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager)
{
_logger = logger;
_sessionManager = sessionManager;
@@ -45,6 +46,7 @@ namespace MediaBrowser.Dlna.PlayTo
_deviceDiscovery = deviceDiscovery;
_httpClient = httpClient;
_config = config;
+ _userDataManager = userDataManager;
}
public void Start()
@@ -103,7 +105,8 @@ namespace MediaBrowser.Dlna.PlayTo
_userManager,
_imageProcessor,
serverAddress,
- _deviceDiscovery);
+ _deviceDiscovery,
+ _userDataManager);
controller.Init(device);
diff --git a/MediaBrowser.Dlna/Ssdp/Datagram.cs b/MediaBrowser.Dlna/Ssdp/Datagram.cs
index 2554d33c6..45f571b4b 100644
--- a/MediaBrowser.Dlna/Ssdp/Datagram.cs
+++ b/MediaBrowser.Dlna/Ssdp/Datagram.cs
@@ -22,6 +22,8 @@ namespace MediaBrowser.Dlna.Ssdp
/// </summary>
public int SendCount { get; private set; }
+ public bool HandleBindError { get; set; }
+
private readonly ILogger _logger;
public Datagram(IPEndPoint toEndPoint, IPEndPoint fromEndPoint, ILogger logger, string message, int totalSendCount)
@@ -42,7 +44,17 @@ namespace MediaBrowser.Dlna.Ssdp
if (FromEndPoint != null)
{
- client.Bind(FromEndPoint);
+ try
+ {
+ client.Bind(FromEndPoint);
+ }
+ catch
+ {
+ if (!HandleBindError)
+ {
+ throw;
+ }
+ }
}
client.BeginSendTo(msg, 0, msg.Length, SocketFlags.None, ToEndPoint, result =>
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index a237a0d67..bee4a3a56 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Dlna.Ssdp
string mx = null;
args.Headers.TryGetValue("mx", out mx);
int delaySeconds;
- if (!string.IsNullOrWhiteSpace(mx) &&
+ if (!string.IsNullOrWhiteSpace(mx) &&
int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds)
&& delaySeconds > 0)
{
@@ -124,18 +124,23 @@ namespace MediaBrowser.Dlna.Ssdp
IPEndPoint localAddress,
int sendCount = 1)
{
- SendDatagram(header, values, _ssdpEndp, localAddress, sendCount);
+ SendDatagram(header, values, _ssdpEndp, localAddress, false, sendCount);
}
public void SendDatagram(string header,
Dictionary<string, string> values,
IPEndPoint endpoint,
IPEndPoint localAddress,
+ bool handleBindError,
int sendCount = 1)
{
var msg = new SsdpMessageBuilder().BuildMessage(header, values);
- var dgram = new Datagram(endpoint, localAddress, _logger, msg, sendCount);
+ var dgram = new Datagram(endpoint, localAddress, _logger, msg, sendCount)
+ {
+ HandleBindError = handleBindError
+ };
+
if (_messageQueue.Count == 0)
{
dgram.Send();
@@ -170,10 +175,7 @@ namespace MediaBrowser.Dlna.Ssdp
values["ST"] = d.Type;
values["USN"] = d.USN;
- // Commenting this out because binding to the local ipendpoint often throws an error
- //SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0));
-
- SendDatagram(header, values, endpoint, null);
+ SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true);
if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index 22873d910..cc753298c 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -91,7 +91,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs
index a97cc3b12..76af08e0c 100644
--- a/MediaBrowser.Model/Entities/CollectionType.cs
+++ b/MediaBrowser.Model/Entities/CollectionType.cs
@@ -26,7 +26,28 @@
public const string Playlists = "playlists";
public const string Folders = "folders";
+ public const string LiveTvNowPlaying = "LiveTvNowPlaying";
public const string LiveTvChannels = "LiveTvChannels";
public const string LiveTvRecordingGroups = "LiveTvRecordingGroups";
+
+ public const string TvSeries = "TvSeries";
+ public const string TvGenres = "TvGenres";
+ public const string TvLatest = "TvLatest";
+ public const string TvNextUp = "TvNextUp";
+ public const string TvResume = "TvResume";
+ public const string TvFavorites = "TvFavorites";
+
+ public const string MovieLatest = "MovieLatest";
+ public const string MovieResume = "MovieResume";
+ public const string MovieMovies = "MovieMovies";
+ public const string MovieCollections = "MovieCollections";
+ public const string MovieFavorites = "MovieFavorites";
+ public const string MovieGenres = "MovieGenres";
+
+ public const string LatestGames = "LatestGames";
+ public const string RecentlyPlayedGames = "RecentlyPlayedGames";
+ public const string GameSystems = "GameSystems";
+ public const string GameGenres = "GameGenres";
+ public const string GameFavorites = "GameFavorites";
}
}
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index a760cba05..082f64bd9 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -372,7 +372,7 @@
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\net45\" /y /d /r /i
)</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<Import Project="Fody.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index b69a4bc2f..995547ce6 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -211,7 +211,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index 504814fe0..924ae12da 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -198,7 +198,7 @@ namespace MediaBrowser.Server.Implementations.Connect
private string GetConnectUrl(string handler)
{
- return "http://mb3admin.com/admin/connect/" + handler;
+ return "http://mediabrowser.tv:8095/" + handler;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index e66899efa..d222c584e 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -196,7 +196,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
try
{
- var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed.HasValue;
+ var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
@@ -308,7 +308,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <param name="options">The options.</param>
private void DrawIndicator(Graphics graphics, int imageWidth, int imageHeight, ImageProcessingOptions options)
{
- if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && !options.PercentPlayed.HasValue)
+ if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
{
return;
}
@@ -328,11 +328,11 @@ namespace MediaBrowser.Server.Implementations.Drawing
new UnplayedCountIndicator().DrawUnplayedCountIndicator(graphics, currentImageSize, options.UnplayedCount.Value);
}
- if (options.PercentPlayed.HasValue)
+ if (options.PercentPlayed >= 0)
{
var currentImageSize = new Size(imageWidth, imageHeight);
- new PercentPlayedDrawer().Process(graphics, currentImageSize, options.PercentPlayed.Value);
+ new PercentPlayedDrawer().Process(graphics, currentImageSize, options.PercentPlayed);
}
}
catch (Exception ex)
@@ -437,7 +437,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <summary>
/// Gets the cache file path based on a set of parameters
/// </summary>
- private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageOutputFormat format, bool addPlayedIndicator, double? percentPlayed, int? unwatchedCount, string backgroundColor)
+ private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageOutputFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor)
{
var filename = originalPath;
@@ -462,9 +462,9 @@ namespace MediaBrowser.Server.Implementations.Drawing
hasIndicator = true;
}
- if (percentPlayed.HasValue)
+ if (percentPlayed > 0)
{
- filename += "p=" + percentPlayed.Value;
+ filename += "p=" + percentPlayed;
hasIndicator = true;
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index d072217af..d2a89e947 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -726,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return result;
}
- public async Task<QueryResult<ProgramInfoDto>> GetRecommendedPrograms(RecommendedProgramQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken)
{
IEnumerable<LiveTvProgram> programs = _programs.Values;
@@ -771,7 +771,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await RefreshIfNeeded(programList, cancellationToken).ConfigureAwait(false);
- var returnArray = programList
+ var returnArray = programList.ToArray();
+
+ var result = new QueryResult<LiveTvProgram>
+ {
+ Items = returnArray,
+ TotalRecordCount = returnArray.Length
+ };
+
+ return result;
+ }
+
+ public async Task<QueryResult<ProgramInfoDto>> GetRecommendedPrograms(RecommendedProgramQuery query, CancellationToken cancellationToken)
+ {
+ var internalResult = await GetRecommendedProgramsInternal(query, cancellationToken).ConfigureAwait(false);
+
+ var user = _userManager.GetUserById(new Guid(query.UserId));
+
+ var returnArray = internalResult.Items
.Select(i =>
{
var channel = GetChannel(i);
@@ -785,7 +802,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var result = new QueryResult<ProgramInfoDto>
{
Items = returnArray,
- TotalRecordCount = returnArray.Length
+ TotalRecordCount = internalResult.TotalRecordCount
};
return result;
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index 2ed67ccf0..1020038f4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -841,6 +841,24 @@
"ViewTypeBoxSets": "Collections",
"ViewTypeChannels": "Channels",
"ViewTypeLiveTV": "Live TV",
+ "ViewTypeLiveTvNowPlaying": "Now Airing",
+ "ViewTypeLatestGames": "Latest Games",
+ "ViewTypeRecentlyPlayedGames": "Recently Played",
+ "ViewTypeGameFavorites": "Favorites",
+ "ViewTypeGameSystems": "Game Systems",
+ "ViewTypeGameGenres": "Genres",
+ "ViewTypeTvResume": "Resume",
+ "ViewTypeTvNextUp": "Next Up",
+ "ViewTypeTvLatest": "Latest",
+ "ViewTypeTvSeries": "Series",
+ "ViewTypeTvGenres": "Genres",
+ "ViewTypeTvFavorites": "Favorites",
+ "ViewTypeMovieResume": "Resume",
+ "ViewTypeMovieLatest": "Latest",
+ "ViewTypeMovieMovies": "Movies",
+ "ViewTypeMovieCollections": "Collections",
+ "ViewTypeMovieFavorites": "Favorites",
+ "ViewTypeMovieGenres": "Genres",
"HeaderOtherDisplaySettings": "Display Settings",
"HeaderMyViews": "My Views",
"LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:",
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 683f74cc3..a03cae78c 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -293,6 +293,7 @@
<Compile Include="Sync\SyncManager.cs" />
<Compile Include="Sync\SyncRepository.cs" />
<Compile Include="Themes\AppThemeManager.cs" />
+ <Compile Include="TV\TVSeriesManager.cs" />
<Compile Include="Udp\UdpMessageReceivedEventArgs.cs" />
<Compile Include="Udp\UdpServer.cs" />
</ItemGroup>
@@ -500,7 +501,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
@@ -508,4 +509,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project> \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
new file mode 100644
index 000000000..e71a5d514
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
@@ -0,0 +1,202 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.TV;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.TV
+{
+ public class TVSeriesManager : ITVSeriesManager
+ {
+ private readonly IUserManager _userManager;
+ private readonly IUserDataManager _userDataManager;
+ private readonly ILibraryManager _libraryManager;
+
+ public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager)
+ {
+ _userManager = userManager;
+ _userDataManager = userDataManager;
+ _libraryManager = libraryManager;
+ }
+
+ public QueryResult<BaseItem> GetNextUp(NextUpQuery request)
+ {
+ var user = _userManager.GetUserById(new Guid(request.UserId));
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ var parentIds = string.IsNullOrEmpty(request.ParentId)
+ ? new string[] { }
+ : new[] { request.ParentId };
+
+ var items = GetAllLibraryItems(user, parentIds)
+ .OfType<Series>();
+
+ // Avoid implicitly captured closure
+ var episodes = GetNextUpEpisodes(request, user, items);
+
+ return GetResult(episodes, null, request);
+ }
+
+ public QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders)
+ {
+ var user = _userManager.GetUserById(new Guid(request.UserId));
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ var items = parentsFolders.SelectMany(i => i.GetRecursiveChildren(user))
+ .OfType<Series>();
+
+ // Avoid implicitly captured closure
+ var episodes = GetNextUpEpisodes(request, user, items);
+
+ return GetResult(episodes, null, request);
+ }
+
+ private IEnumerable<BaseItem> GetAllLibraryItems(User user, string[] parentIds)
+ {
+ if (parentIds.Length > 0)
+ {
+ return parentIds.SelectMany(i =>
+ {
+ var folder = (Folder)_libraryManager.GetItemById(new Guid(i));
+
+ return folder.GetRecursiveChildren(user);
+
+ });
+ }
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return user.RootFolder.GetRecursiveChildren(user);
+ }
+
+ public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable<Series> series)
+ {
+ // Avoid implicitly captured closure
+ var currentUser = user;
+
+ return FilterSeries(request, series)
+ .AsParallel()
+ .Select(i => GetNextUp(i, currentUser))
+ .Where(i => i.Item1 != null)
+ .OrderByDescending(i =>
+ {
+ var episode = i.Item1;
+
+ var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey());
+
+ if (seriesUserData.IsFavorite)
+ {
+ return 2;
+ }
+
+ if (seriesUserData.Likes.HasValue)
+ {
+ return seriesUserData.Likes.Value ? 1 : -1;
+ }
+
+ return 0;
+ })
+ .ThenByDescending(i => i.Item2)
+ .ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
+ .Select(i => i.Item1);
+ }
+
+ /// <summary>
+ /// Gets the next up.
+ /// </summary>
+ /// <param name="series">The series.</param>
+ /// <param name="user">The user.</param>
+ /// <returns>Task{Episode}.</returns>
+ private Tuple<Episode, DateTime> GetNextUp(Series series, User user)
+ {
+ // Get them in display order, then reverse
+ var allEpisodes = series.GetSeasons(user, true, true)
+ .SelectMany(i => i.GetEpisodes(user, true, true))
+ .Reverse()
+ .ToList();
+
+ Episode lastWatched = null;
+ var lastWatchedDate = DateTime.MinValue;
+ Episode nextUp = null;
+
+ // Go back starting with the most recent episodes
+ foreach (var episode in allEpisodes)
+ {
+ var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey());
+
+ if (userData.Played)
+ {
+ if (lastWatched != null || nextUp == null)
+ {
+ break;
+ }
+
+ lastWatched = episode;
+ lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue;
+ }
+ else
+ {
+ if (episode.LocationType != LocationType.Virtual)
+ {
+ nextUp = episode;
+ }
+ }
+ }
+
+ if (lastWatched != null)
+ {
+ return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate);
+ }
+
+ return new Tuple<Episode, DateTime>(null, lastWatchedDate);
+ }
+
+ private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items)
+ {
+ if (!string.IsNullOrWhiteSpace(request.SeriesId))
+ {
+ var id = new Guid(request.SeriesId);
+
+ items = items.Where(i => i.Id == id);
+ }
+
+ return items;
+ }
+
+ private QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, int? totalRecordLimit, NextUpQuery query)
+ {
+ var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();
+ var totalCount = itemsArray.Length;
+
+ if (query.Limit.HasValue)
+ {
+ itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray();
+ }
+ else if (query.StartIndex.HasValue)
+ {
+ itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
+ }
+
+ return new QueryResult<BaseItem>
+ {
+ TotalRecordCount = totalCount,
+ Items = itemsArray
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 51dccddff..e97c21204 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -38,6 +38,7 @@ using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Controller.Themes;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Dlna;
using MediaBrowser.Dlna.ConnectionManager;
using MediaBrowser.Dlna.ContentDirectory;
@@ -79,6 +80,7 @@ using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
using MediaBrowser.Server.Implementations.Sync;
using MediaBrowser.Server.Implementations.Themes;
+using MediaBrowser.Server.Implementations.TV;
using MediaBrowser.ServerApplication.FFMpeg;
using MediaBrowser.ServerApplication.IO;
using MediaBrowser.ServerApplication.Native;
@@ -213,10 +215,11 @@ namespace MediaBrowser.ServerApplication
private ISubtitleManager SubtitleManager { get; set; }
private IChapterManager ChapterManager { get; set; }
- private IUserViewManager UserViewManager { get; set; }
+ internal IUserViewManager UserViewManager { get; set; }
private IAuthenticationRepository AuthenticationRepository { get; set; }
private ISyncRepository SyncRepository { get; set; }
+ private ITVSeriesManager TVSeriesManager { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
@@ -466,6 +469,9 @@ namespace MediaBrowser.ServerApplication
ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager);
RegisterSingleInstance(ChannelManager);
+ TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager);
+ RegisterSingleInstance(TVSeriesManager);
+
var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
RegisterSingleInstance<IAppThemeManager>(appThemeManager);
@@ -487,7 +493,7 @@ namespace MediaBrowser.ServerApplication
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, FileSystemManager, UserManager, ChannelManager, LiveTvManager, ApplicationPaths, playlistManager);
RegisterSingleInstance(UserViewManager);
- var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, UserViewManager, ChannelManager);
+ var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient);
RegisterSingleInstance<IContentDirectory>(contentDirectory);
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
@@ -682,9 +688,10 @@ namespace MediaBrowser.ServerApplication
Folder.UserManager = UserManager;
BaseItem.FileSystem = FileSystemManager;
BaseItem.UserDataManager = UserDataManager;
- ChannelVideoItem.ChannelManager = ChannelManager;
+ BaseItem.ChannelManager = ChannelManager;
BaseItem.LiveTvManager = LiveTvManager;
- UserView.UserViewManager = UserViewManager;
+ Folder.UserViewManager = UserViewManager;
+ UserView.TVSeriesManager = TVSeriesManager;
}
/// <summary>
diff --git a/MediaBrowser.ServerApplication/LibraryViewer.cs b/MediaBrowser.ServerApplication/LibraryViewer.cs
index 26cf243da..e89cbd0c0 100644
--- a/MediaBrowser.ServerApplication/LibraryViewer.cs
+++ b/MediaBrowser.ServerApplication/LibraryViewer.cs
@@ -1,6 +1,9 @@
-using MediaBrowser.Controller.Entities;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using System;
@@ -16,17 +19,17 @@ namespace MediaBrowser.ServerApplication
{
private readonly IJsonSerializer _jsonSerializer;
private readonly ILibraryManager _libraryManager;
- private readonly IItemRepository _itemRepository;
+ private readonly IUserViewManager _userViewManager;
private User _currentUser;
- public LibraryViewer(IJsonSerializer jsonSerializer, IUserManager userManager, ILibraryManager libraryManager, IItemRepository itemRepo)
+ public LibraryViewer(IJsonSerializer jsonSerializer, IUserManager userManager, ILibraryManager libraryManager, IUserViewManager userViewManager)
{
InitializeComponent();
_jsonSerializer = jsonSerializer;
_libraryManager = libraryManager;
- _itemRepository = itemRepo;
+ _userViewManager = userViewManager;
foreach (var user in userManager.Users)
selectUser.Items.Add(user);
@@ -72,23 +75,50 @@ namespace MediaBrowser.ServerApplication
LoadTree();
}
+ private IEnumerable<BaseItem> GetItems(Folder parent, User user)
+ {
+ if (parent == null)
+ {
+ var task = _userViewManager.GetUserViews(new UserViewQuery
+ {
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None);
+
+ task.RunSynchronously();
+
+ return task.Result;
+ }
+ else
+ {
+ var task = parent.GetUserItems(new UserItemsQuery
+ {
+ User = user,
+ SortBy = new[] { ItemSortBy.SortName }
+
+ });
+
+ task.RunSynchronously();
+
+ return task.Result.Items;
+ }
+ }
+
private void LoadTree()
{
treeView1.Nodes.Clear();
var isPhysical = _currentUser.Name == "Physical";
- IEnumerable<BaseItem> children = isPhysical ? new[] { _libraryManager.RootFolder } : _libraryManager.RootFolder.GetChildren(_currentUser, true);
- children = OrderByName(children, _currentUser);
+ IEnumerable<BaseItem> children = isPhysical ? new[] { _libraryManager.RootFolder } : GetItems(null, _currentUser);
- foreach (Folder folder in children)
+ foreach (var folder in children.OfType<Folder>())
{
-
var currentFolder = folder;
var node = new TreeNode { Tag = currentFolder };
- var subChildren = isPhysical ? currentFolder.Children : currentFolder.GetChildren(_currentUser, true);
- subChildren = OrderByName(subChildren, _currentUser);
+ var subChildren = isPhysical ? currentFolder.Children.OrderBy(i => i.SortName) : GetItems(currentFolder, _currentUser);
+
AddChildren(node, subChildren, _currentUser, isPhysical);
node.Text = currentFolder.Name + " (" +
node.Nodes.Count + ")";
@@ -111,9 +141,9 @@ namespace MediaBrowser.ServerApplication
var subFolder = item as Folder;
if (subFolder != null)
{
- var subChildren = isPhysical ? subFolder.Children : subFolder.GetChildren(_currentUser, true);
+ var subChildren = isPhysical ? subFolder.Children.OrderBy(i => i.SortName) : GetItems(subFolder, _currentUser);
- AddChildren(node, OrderBy(subChildren, user, ItemSortBy.SortName), user, isPhysical);
+ AddChildren(node, subChildren, user, isPhysical);
node.Text = item.Name + " (" + node.Nodes.Count + ")";
}
else
@@ -125,28 +155,6 @@ namespace MediaBrowser.ServerApplication
}
/// <summary>
- /// Orders the name of the by.
- /// </summary>
- /// <param name="items">The items.</param>
- /// <param name="user">The user.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- private IEnumerable<BaseItem> OrderByName(IEnumerable<BaseItem> items, User user)
- {
- return OrderBy(items, user, ItemSortBy.SortName);
- }
-
- /// <summary>
- /// Orders the name of the by.
- /// </summary>
- /// <param name="items">The items.</param>
- /// <param name="user">The user.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- private IEnumerable<BaseItem> OrderBy(IEnumerable<BaseItem> items, User user, string order)
- {
- return _libraryManager.Sort(items, user, new[] { order }, SortOrder.Ascending);
- }
-
- /// <summary>
/// The INDEN t_ STRING
/// </summary>
private const string INDENT_STRING = " ";
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 81c04060a..6e6377a64 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -249,7 +249,7 @@ namespace MediaBrowser.ServerApplication
{
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
- _serverNotifyIcon = new ServerNotifyIcon(_appHost.LogManager, _appHost, _appHost.ServerConfigurationManager, _appHost.UserManager, _appHost.LibraryManager, _appHost.JsonSerializer, _appHost.ItemRepository, _appHost.LocalizationManager);
+ _serverNotifyIcon = new ServerNotifyIcon(_appHost.LogManager, _appHost, _appHost.ServerConfigurationManager, _appHost.UserManager, _appHost.LibraryManager, _appHost.JsonSerializer, _appHost.LocalizationManager, _appHost.UserViewManager);
Application.Run();
}
diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
index 47a4be8e3..8740b707b 100644
--- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
+++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.ServerApplication
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
private readonly IJsonSerializer _jsonSerializer;
- private readonly IItemRepository _itemRepository;
+ private readonly IUserViewManager _userViewManager;
private readonly ILocalizationManager _localization;
private LogForm _logForm;
@@ -61,11 +61,11 @@ namespace MediaBrowser.ServerApplication
IServerConfigurationManager configurationManager,
IUserManager userManager, ILibraryManager libraryManager,
IJsonSerializer jsonSerializer,
- IItemRepository itemRepo, ILocalizationManager localization)
+ ILocalizationManager localization, IUserViewManager userViewManager)
{
_logger = logManager.GetLogger("MainWindow");
- _itemRepository = itemRepo;
_localization = localization;
+ _userViewManager = userViewManager;
_appHost = appHost;
_logManager = logManager;
_configurationManager = configurationManager;
@@ -318,7 +318,7 @@ namespace MediaBrowser.ServerApplication
void cmdLibraryExplorer_Click(object sender, EventArgs e)
{
- new LibraryViewer(_jsonSerializer, _userManager, _libraryManager, _itemRepository).Show();
+ new LibraryViewer(_jsonSerializer, _userManager, _libraryManager, _userViewManager).Show();
}
void cmdRestart_Click(object sender, EventArgs e)
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 32cb88218..864a2f70f 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -2136,7 +2136,7 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">