fixes #912 - Add special views for Dlna
This commit is contained in:
parent
383b9999da
commit
6f45ea0823
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 result = _tvSeriesManager.GetNextUp(new NextUpQuery
|
||||
{
|
||||
Limit = request.Limit,
|
||||
ParentId = request.ParentId,
|
||||
SeriesId = request.SeriesId,
|
||||
StartIndex = request.StartIndex,
|
||||
UserId = request.UserId
|
||||
});
|
||||
|
||||
var itemsList = GetNextUpEpisodes(request)
|
||||
.ToList();
|
||||
|
||||
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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
35
MediaBrowser.Controller/Entities/UserItemsQuery.cs
Normal file
35
MediaBrowser.Controller/Entities/UserItemsQuery.cs
Normal file
|
@ -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[] { };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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 static ITVSeriesManager TVSeriesManager;
|
||||
|
||||
public override Task<QueryResult<BaseItem>> GetUserItems(UserItemsQuery query)
|
||||
{
|
||||
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager)
|
||||
.GetUserItems(this, ViewType, query);
|
||||
}
|
||||
|
||||
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||
{
|
||||
var mediaFolders = GetMediaFolders(user);
|
||||
|
||||
switch (ViewType)
|
||||
var result = GetUserItems(new UserItemsQuery
|
||||
{
|
||||
case CollectionType.LiveTvChannels:
|
||||
return LiveTvManager.GetInternalChannels(new LiveTvChannelQuery
|
||||
{
|
||||
UserId = user.Id.ToString("N")
|
||||
User = user
|
||||
|
||||
}, CancellationToken.None).Result.Items;
|
||||
case CollectionType.LiveTvRecordingGroups:
|
||||
return LiveTvManager.GetInternalRecordings(new RecordingQuery
|
||||
{
|
||||
UserId = user.Id.ToString("N"),
|
||||
Status = RecordingStatus.Completed
|
||||
}).Result;
|
||||
|
||||
}, 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));
|
||||
}
|
||||
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>
|
||||
|
|
614
MediaBrowser.Controller/Entities/UserViewBuilder.cs
Normal file
614
MediaBrowser.Controller/Entities/UserViewBuilder.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -244,6 +244,15 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
Task<QueryResult<ProgramInfoDto>> GetRecommendedPrograms(RecommendedProgramQuery query,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recommended programs internal.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<QueryResult<LiveTvProgram>>.</returns>
|
||||
Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the live tv information.
|
||||
/// </summary>
|
||||
|
|
|
@ -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">
|
||||
|
|
24
MediaBrowser.Controller/TV/ITVSeriesManager.cs
Normal file
24
MediaBrowser.Controller/TV/ITVSeriesManager.cs
Normal file
|
@ -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<BaseItem>.</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<BaseItem>.</returns>
|
||||
QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
items = SortItems(items, user, sort);
|
||||
|
||||
return ToResult(items, startIndex, limit);
|
||||
}).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 sortOrders = new List<string>();
|
||||
if (!folder.IsPreSorted)
|
||||
{
|
||||
var result = await _userViewManager.GetUserViews(new UserViewQuery
|
||||
{
|
||||
UserId = user.Id.ToString("N")
|
||||
|
||||
}, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
return ToResult(result, startIndex, limit);
|
||||
sortOrders.Add(ItemSortBy.SortName);
|
||||
}
|
||||
|
||||
var view = folder as UserView;
|
||||
|
||||
if (view != null)
|
||||
return await folder.GetUserItems(new UserItemsQuery
|
||||
{
|
||||
var result = await GetUserViewChildren(view, user, sort).ConfigureAwait(false);
|
||||
Limit = limit,
|
||||
StartIndex = startIndex,
|
||||
SortBy = sortOrders.ToArray(),
|
||||
SortOrder = sort.SortOrder,
|
||||
User = user,
|
||||
Filter = FilterUnsupportedContent
|
||||
|
||||
return ToResult(result, startIndex, limit);
|
||||
}
|
||||
|
||||
var channel = folder as Channel;
|
||||
|
||||
if (channel != 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 = channel.Id.ToString("N"),
|
||||
Limit = limit,
|
||||
StartIndex = startIndex,
|
||||
UserId = user.Id.ToString("N")
|
||||
|
||||
}, CancellationToken.None);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Already logged at lower levels
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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 false;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 =>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:",
|
||||
|
|
|
@ -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>
|
202
MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
Normal file
202
MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
Normal file
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
@ -124,28 +154,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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue
Block a user