fixes #912 - Add special views for Dlna

This commit is contained in:
Luke Pulverenti
2014-09-01 16:10:54 -04:00
parent 383b9999da
commit 6f45ea0823
44 changed files with 1326 additions and 482 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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:",

View File

@@ -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>

View 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
};
}
}
}