From b7b8cb508431635ff777bcf59d4ab25785471e4f Mon Sep 17 00:00:00 2001 From: 7illusions Date: Sat, 8 Mar 2014 22:36:12 +0100 Subject: Added UserId To API Remotecontrol-calls --- MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Model.Portable') diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 04296de355..ccc05492ca 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -11,12 +11,17 @@ MediaBrowser.Model MediaBrowser.Model v4.0 - Profile104 + Profile158 512 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\ true ..\packages\Fody.1.19.1.0 + + + + + 4.0 true -- cgit v1.2.3 From 38e5e32b42a2eb217457cbd42e8c26b46d401b23 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 10 Mar 2014 13:38:53 -0400 Subject: added play to config page --- MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs | 91 +++++++++++++++++++--- .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + MediaBrowser.Model/Configuration/DlnaOptions.cs | 8 ++ .../Configuration/ServerConfiguration.cs | 4 + MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + .../Collections/CollectionManager.cs | 8 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 1 + .../MediaBrowser.WebDashboard.csproj | 6 ++ MediaBrowser.sln | 2 +- 10 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 MediaBrowser.Model/Configuration/DlnaOptions.cs (limited to 'MediaBrowser.Model.Portable') diff --git a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs index b1afeb0f4a..a6746cfc50 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs @@ -1,40 +1,107 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Logging; +using System; namespace MediaBrowser.Dlna.PlayTo { public class PlayToServerEntryPoint : IServerEntryPoint { - private bool _disposed; + private PlayToManager _manager; + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ISessionManager _sessionManager; + private readonly IHttpClient _httpClient; + private readonly IItemRepository _itemRepo; + private readonly ILibraryManager _libraryManager; + private readonly INetworkManager _networkManager; + private readonly IUserManager _userManager; - private readonly PlayToManager _manager; - - public PlayToServerEntryPoint(ILogManager logManager, ISessionManager sessionManager, IUserManager userManager, IHttpClient httpClient, INetworkManager networkManager, IItemRepository itemRepository, ILibraryManager libraryManager) + public PlayToServerEntryPoint(ILogManager logManager, IServerConfigurationManager config, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, INetworkManager networkManager, IUserManager userManager) { - _manager = new PlayToManager(logManager.GetLogger("PlayTo"), sessionManager, httpClient, itemRepository, libraryManager, networkManager, userManager); + _config = config; + _sessionManager = sessionManager; + _httpClient = httpClient; + _itemRepo = itemRepo; + _libraryManager = libraryManager; + _networkManager = networkManager; + _userManager = userManager; + _logger = logManager.GetLogger("PlayTo"); } public void Run() { - //_manager.Start(); + _config.ConfigurationUpdated += ConfigurationUpdated; + ReloadPlayToManager(); } - #region Dispose + void ConfigurationUpdated(object sender, EventArgs e) + { + ReloadPlayToManager(); + } - public void Dispose() + private void ReloadPlayToManager() + { + var isStarted = _manager != null; + + if (_config.Configuration.DlnaOptions.EnablePlayTo && !isStarted) + { + StartPlayToManager(); + } + else if (!_config.Configuration.DlnaOptions.EnablePlayTo && isStarted) + { + DisposePlayToManager(); + } + } + + private readonly object _syncLock = new object(); + private void StartPlayToManager() + { + lock (_syncLock) + { + try + { + _manager = new PlayToManager(_logger, _sessionManager, _httpClient, _itemRepo, _libraryManager, _networkManager, _userManager); + _manager.Start(); + } + catch (Exception ex) + { + _logger.ErrorException("Error starting PlayTo manager", ex); + } + } + } + + private void DisposePlayToManager() { - if (!_disposed) + lock (_syncLock) { - _disposed = true; - _manager.Stop(); - _manager.Dispose(); + if (_manager != null) + { + try + { + _manager.Stop(); + _manager.Dispose(); + } + catch (Exception ex) + { + _logger.ErrorException("Error disposing PlayTo manager", ex); + } + _manager = null; + } } } + #region Dispose + + public void Dispose() + { + DisposePlayToManager(); + } + #endregion } } diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 04296de355..8dd8a2a346 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -80,6 +80,9 @@ Configuration\BaseApplicationConfiguration.cs + + Configuration\DlnaOptions.cs + Configuration\ManualLoginCategory.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 56f7fb99d2..4cdcaae64f 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -67,6 +67,9 @@ Configuration\BaseApplicationConfiguration.cs + + Configuration\DlnaOptions.cs + Configuration\ManualLoginCategory.cs diff --git a/MediaBrowser.Model/Configuration/DlnaOptions.cs b/MediaBrowser.Model/Configuration/DlnaOptions.cs new file mode 100644 index 0000000000..e6c24fdfb6 --- /dev/null +++ b/MediaBrowser.Model/Configuration/DlnaOptions.cs @@ -0,0 +1,8 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class DlnaOptions + { + public bool EnablePlayTo { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 0bff8a1bdf..c2765754e9 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -212,6 +212,8 @@ namespace MediaBrowser.Model.Configuration public string ServerName { get; set; } public string WanDdns { get; set; } + public DlnaOptions DlnaOptions { get; set; } + /// /// Initializes a new instance of the class. /// @@ -271,6 +273,8 @@ namespace MediaBrowser.Model.Configuration }; MetadataOptions = options.ToArray(); + + DlnaOptions = new DlnaOptions(); } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 10aedb3baf..42ae7c396a 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -60,6 +60,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index 1cfcef5140..9a196cc47a 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -81,7 +81,13 @@ namespace MediaBrowser.Server.Implementations.Collections throw new ArgumentNullException("parentId"); } - return _libraryManager.GetItemById(parentId.Value) as Folder; + var folder = _libraryManager.GetItemById(parentId.Value) as Folder; + + // Find an actual physical folder + if (folder is CollectionFolder) + { + return _libraryManager.RootFolder.Children.OfType().First(i => folder.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)); + } } return _libraryManager.RootFolder.Children.OfType().FirstOrDefault() ?? diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 19f213b2ff..fa2ae278c7 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -480,6 +480,7 @@ namespace MediaBrowser.WebDashboard.Api "dashboardinfo.js", "dashboardpage.js", "directorybrowser.js", + "dlnasettings.js", "editcollectionitems.js", "edititemmetadata.js", "edititempeople.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 424192e283..4b2ce4833f 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -213,6 +213,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -483,6 +486,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 7ac1580659..1d8a3bf265 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -254,4 +254,4 @@ Global GlobalSection(Performance) = preSolution HasPerformanceSessions = true EndGlobalSection -EndGlobal +EndGlobal \ No newline at end of file -- cgit v1.2.3 From 6825cad56221775dfdfc88bbf260cd1399fa4313 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 11 Mar 2014 22:11:01 -0400 Subject: move collections back under movies. add movie suggestions page. --- MediaBrowser.Api/Movies/MoviesService.cs | 244 ++++++++++++++++++++- MediaBrowser.Api/SimilarItemsHelper.cs | 10 +- MediaBrowser.Api/TvShowsService.cs | 15 +- MediaBrowser.Controller/Channels/IChannel.cs | 16 +- .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + MediaBrowser.Model/Dto/RecommendationDto.cs | 29 +++ MediaBrowser.Model/Entities/BaseItemInfo.cs | 24 ++ MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Providers/Manager/MetadataService.cs | 22 +- .../Dto/DtoService.cs | 51 +++++ .../Library/LibraryManager.cs | 1 + .../Library/Resolvers/Movies/MovieResolver.cs | 25 +-- MediaBrowser.WebDashboard/Api/DashboardService.cs | 1 + .../MediaBrowser.WebDashboard.csproj | 6 + MediaBrowser.sln | 2 +- 16 files changed, 408 insertions(+), 45 deletions(-) create mode 100644 MediaBrowser.Model/Dto/RecommendationDto.cs (limited to 'MediaBrowser.Model.Portable') diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 5d97d13e15..667a86fe6a 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -1,9 +1,16 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using ServiceStack; +using System; +using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Api.Movies { @@ -23,6 +30,32 @@ namespace MediaBrowser.Api.Movies } } + [Route("/Movies/Recommendations", "GET")] + [Api(Description = "Gets movie recommendations")] + public class GetMovieRecommendations : IReturn, IHasItemFields + { + [ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int CategoryLimit { get; set; } + + [ApiMember(Name = "ItemLimit", Description = "The max number of items to return per category", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int ItemLimit { get; set; } + + /// + /// Gets or sets the user id. + /// + /// The user id. + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + + public GetMovieRecommendations() + { + CategoryLimit = 5; + ItemLimit = 8; + } + + public string Fields { get; set; } + } + /// /// Class MoviesService /// @@ -78,5 +111,214 @@ namespace MediaBrowser.Api.Movies return ToOptimizedSerializedResultUsingCache(result); } + + public object Get(GetMovieRecommendations request) + { + var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null; + + var folder = user.RootFolder; + var movies = folder.RecursiveChildren.OfType().ToList(); + + var result = GetRecommendationCategories(user, movies, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList()); + + return ToOptimizedResult(result); + } + + private IEnumerable GetRecommendationCategories(User user, List allMovies, int categoryLimit, int itemLimit, List fields) + { + var categories = new List(); + + var recentlyPlayedMovies = allMovies + .Select(i => + { + var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + return new Tuple(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue); + }) + .Where(i => i.Item2) + .OrderByDescending(i => i.Item3) + .Select(i => i.Item1) + .ToList(); + + var excludeFromLiked = recentlyPlayedMovies.Take(10); + var likedMovies = allMovies + .Select(i => + { + var score = 0; + var userData = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + + if (userData.IsFavorite) + { + score = 2; + } + else + { + score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0; + } + + return new Tuple(i, score); + }) + .OrderByDescending(i => i.Item2) + .ThenBy(i => Guid.NewGuid()) + .Where(i => i.Item2 > 0) + .Select(i => i.Item1) + .Where(i => !excludeFromLiked.Contains(i)); + + var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList(); + // Get recently played directors + var recentDirectors = GetDirectors(mostRecentMovies) + .OrderBy(i => Guid.NewGuid()) + .ToList(); + + // Get recently played actors + var recentActors = GetActors(mostRecentMovies) + .OrderBy(i => Guid.NewGuid()) + .ToList(); + + var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(10).OrderBy(i => Guid.NewGuid()), itemLimit, fields, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator(); + var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, fields, RecommendationType.SimilarToLikedItem).GetEnumerator(); + + var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, fields, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator(); + var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, fields, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator(); + + var categoryTypes = new List> + { + // Give this extra weight + similarToRecentlyPlayed, + similarToRecentlyPlayed, + + // Give this extra weight + similarToLiked, + similarToLiked, + + hasDirectorFromRecentlyPlayed, + hasActorFromRecentlyPlayed + }; + + while (categories.Count < categoryLimit) + { + var allEmpty = true; + + foreach (var category in categoryTypes) + { + if (category.MoveNext()) + { + categories.Add(category.Current); + allEmpty = false; + + if (categories.Count >= categoryLimit) + { + break; + } + } + } + + if (allEmpty) + { + break; + } + } + + //// Get the lead actor for all movies + //var allActors = GetActors(allMovies) + // .ToList(); + + //foreach (var actor in recentActors) + //{ + + //} + + return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid()); + } + + private IEnumerable GetWithDirector(User user, List allMovies, IEnumerable directors, int itemLimit, List fields, RecommendationType type) + { + var userId = user.Id; + + foreach (var director in directors) + { + var items = allMovies + .Where(i => !_userDataRepository.GetUserData(userId, i.GetUserDataKey()).Played && i.People.Any(p => string.Equals(p.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Name, director, StringComparison.OrdinalIgnoreCase))) + .Take(itemLimit) + .ToList(); + + if (items.Count > 0) + { + yield return new RecommendationDto + { + BaselineItemName = director, + CategoryId = director.GetMD5().ToString("N"), + RecommendationType = type, + Items = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray() + }; + } + } + } + + private IEnumerable GetWithActor(User user, List allMovies, IEnumerable names, int itemLimit, List fields, RecommendationType type) + { + var userId = user.Id; + + foreach (var name in names) + { + var items = allMovies + .Where(i => !_userDataRepository.GetUserData(userId, i.GetUserDataKey()).Played && i.People.Any(p => string.Equals(p.Name, name, StringComparison.OrdinalIgnoreCase))) + .Take(itemLimit) + .ToList(); + + if (items.Count > 0) + { + yield return new RecommendationDto + { + BaselineItemName = name, + CategoryId = name.GetMD5().ToString("N"), + RecommendationType = type, + Items = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray() + }; + } + } + } + + private IEnumerable GetSimilarTo(User user, List allMovies, IEnumerable baselineItems, int itemLimit, List fields, RecommendationType type) + { + var userId = user.Id; + + foreach (var item in baselineItems) + { + var similar = SimilarItemsHelper + .GetSimilaritems(item, allMovies, SimilarItemsHelper.GetSimiliarityScore) + .Where(i => !_userDataRepository.GetUserData(userId, i.GetUserDataKey()).Played) + .Take(itemLimit) + .ToList(); + + if (similar.Count > 0) + { + yield return new RecommendationDto + { + BaselineItemName = item.Name, + CategoryId = item.Id.ToString("N"), + RecommendationType = type, + Items = similar.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray() + }; + } + } + } + + private IEnumerable GetActors(IEnumerable items) + { + // Get the two leading actors for all movies + return items + .SelectMany(i => i.People.Where(p => !string.Equals(PersonType.Director, p.Type, StringComparison.OrdinalIgnoreCase)).Take(2)) + .Select(i => i.Name) + .Distinct(StringComparer.OrdinalIgnoreCase); + } + + private IEnumerable GetDirectors(IEnumerable items) + { + return items + .Select(i => i.People.FirstOrDefault(p => string.Equals(PersonType.Director, p.Type, StringComparison.OrdinalIgnoreCase))) + .Where(i => i != null) + .Select(i => i.Name) + .Distinct(StringComparer.OrdinalIgnoreCase); + } } } diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index d1dc801bcd..abc4ece65b 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Api var item = string.IsNullOrEmpty(request.Id) ? (request.UserId.HasValue ? user.RootFolder : - (Folder)libraryManager.RootFolder) : dtoService.GetItemByDtoId(request.Id, request.UserId); + libraryManager.RootFolder) : dtoService.GetItemByDtoId(request.Id, request.UserId); var fields = request.GetItemFields().ToList(); @@ -81,7 +81,7 @@ namespace MediaBrowser.Api ? libraryManager.RootFolder.GetRecursiveChildren(i => i.Id != item.Id) : user.RootFolder.GetRecursiveChildren(user, i => i.Id != item.Id); - var items = GetSimilaritems(item, inputItems, includeInSearch, getSimilarityScore) + var items = GetSimilaritems(item, inputItems.Where(includeInSearch), getSimilarityScore) .ToList(); IEnumerable returnItems = items; @@ -106,12 +106,12 @@ namespace MediaBrowser.Api /// /// The item. /// The input items. - /// The include in search. /// The get similarity score. /// IEnumerable{BaseItem}. - internal static IEnumerable GetSimilaritems(BaseItem item, IEnumerable inputItems, Func includeInSearch, Func getSimilarityScore) + internal static IEnumerable GetSimilaritems(BaseItem item, IEnumerable inputItems, Func getSimilarityScore) { - inputItems = inputItems.Where(includeInSearch); + var itemId = item.Id; + inputItems = inputItems.Where(i => i.Id != itemId); return inputItems.Select(i => new Tuple(i, getSimilarityScore(item, i))) .Where(i => i.Item2 > 2) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 198e1c3839..9e58c9f53d 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -300,11 +300,13 @@ namespace MediaBrowser.Api return FilterSeries(request, series) .AsParallel() - .Select(i => GetNextUp(i, currentUser, request).Item1) - .Where(i => i != null) + .Select(i => GetNextUp(i, currentUser)) + .Where(i => i.Item1 != null) .OrderByDescending(i => { - var seriesUserData = _userDataManager.GetUserData(user.Id, i.Series.GetUserDataKey()); + var episode = i.Item1; + + var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey()); if (seriesUserData.IsFavorite) { @@ -318,7 +320,9 @@ namespace MediaBrowser.Api return 0; }) - .ThenByDescending(i => i.PremiereDate ?? DateTime.MinValue); + .ThenByDescending(i =>i.Item2) + .ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue) + .Select(i => i.Item1); } /// @@ -326,9 +330,8 @@ namespace MediaBrowser.Api /// /// The series. /// The user. - /// The request. /// Task{Episode}. - private Tuple GetNextUp(Series series, User user, GetNextUpEpisodes request) + private Tuple GetNextUp(Series series, User user) { // Get them in display order, then reverse var allEpisodes = series.GetSeasons(user, true, true) diff --git a/MediaBrowser.Controller/Channels/IChannel.cs b/MediaBrowser.Controller/Channels/IChannel.cs index edb2347c05..ba1bd40832 100644 --- a/MediaBrowser.Controller/Channels/IChannel.cs +++ b/MediaBrowser.Controller/Channels/IChannel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using MediaBrowser.Controller.Entities; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -28,30 +29,31 @@ namespace MediaBrowser.Controller.Channels /// Searches the specified search term. /// /// The search term. + /// The user. /// The cancellation token. /// Task{IEnumerable{ChannelItemInfo}}. - Task> Search(string searchTerm, CancellationToken cancellationToken); - + Task> Search(string searchTerm, User user, CancellationToken cancellationToken); + /// /// Gets the channel items. /// + /// The user. /// The cancellation token. /// Task{IEnumerable{ChannelItem}}. - Task> GetChannelItems(CancellationToken cancellationToken); + Task> GetChannelItems(User user, CancellationToken cancellationToken); /// /// Gets the channel items. /// /// The category identifier. + /// The user. /// The cancellation token. /// Task{IEnumerable{ChannelItem}}. - Task> GetChannelItems(string categoryId, CancellationToken cancellationToken); + Task> GetChannelItems(string categoryId, User user, CancellationToken cancellationToken); } public class ChannelCapabilities { public bool CanSearch { get; set; } - - public bool CanBeIndexed { get; set; } } } diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 8dd8a2a346..c8df3931d9 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -134,6 +134,9 @@ Dto\ItemIndex.cs + + Dto\RecommendationDto.cs + Dto\StreamOptions.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 4cdcaae64f..6e8f230890 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -121,6 +121,9 @@ Dto\ItemIndex.cs + + Dto\RecommendationDto.cs + Dto\StreamOptions.cs diff --git a/MediaBrowser.Model/Dto/RecommendationDto.cs b/MediaBrowser.Model/Dto/RecommendationDto.cs new file mode 100644 index 0000000000..68b71e466b --- /dev/null +++ b/MediaBrowser.Model/Dto/RecommendationDto.cs @@ -0,0 +1,29 @@ + +namespace MediaBrowser.Model.Dto +{ + public class RecommendationDto + { + public BaseItemDto[] Items { get; set; } + + public RecommendationType RecommendationType { get; set; } + + public string BaselineItemName { get; set; } + + public string CategoryId { get; set; } + } + + public enum RecommendationType + { + SimilarToRecentlyPlayed = 0, + + SimilarToLikedItem = 1, + + HasDirectorFromRecentlyPlayed = 2, + + HasActorFromRecentlyPlayed = 3, + + HasLikedDirector = 4, + + HasLikedActor = 5 + } +} diff --git a/MediaBrowser.Model/Entities/BaseItemInfo.cs b/MediaBrowser.Model/Entities/BaseItemInfo.cs index 49f3e2d8ff..b704bdb57c 100644 --- a/MediaBrowser.Model/Entities/BaseItemInfo.cs +++ b/MediaBrowser.Model/Entities/BaseItemInfo.cs @@ -46,6 +46,30 @@ namespace MediaBrowser.Model.Entities /// The primary image tag. public Guid? PrimaryImageTag { get; set; } + /// + /// Gets or sets the thumb image tag. + /// + /// The thumb image tag. + public Guid? ThumbImageTag { get; set; } + + /// + /// Gets or sets the thumb item identifier. + /// + /// The thumb item identifier. + public string ThumbItemId { get; set; } + + /// + /// Gets or sets the thumb image tag. + /// + /// The thumb image tag. + public Guid? BackdropImageTag { get; set; } + + /// + /// Gets or sets the thumb item identifier. + /// + /// The thumb item identifier. + public string BackdropItemId { get; set; } + /// /// Gets a value indicating whether this instance has primary image. /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 42ae7c396a..45172da43b 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -74,6 +74,7 @@ + diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 2ecc6c9dd8..74b54fe2ce 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -305,22 +305,20 @@ namespace MediaBrowser.Providers.Manager refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.ImageUpdate; } - if (!string.IsNullOrEmpty(localItem.Item.Name)) + if (string.IsNullOrWhiteSpace(localItem.Item.Name)) { - MergeData(localItem.Item, temp, new List(), !options.ReplaceAllMetadata, true); - refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport; - - // Only one local provider allowed per item - hasLocalMetadata = true; - break; + localItem.Item.Name = item.Name ?? Path.GetFileNameWithoutExtension(item.Path); } - Logger.Error("Invalid local metadata found for: " + item.Path); - } - else - { - Logger.Debug("{0} returned no metadata for {1}", providerName, item.Path ?? item.Name); + MergeData(localItem.Item, temp, new List(), !options.ReplaceAllMetadata, true); + refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport; + + // Only one local provider allowed per item + hasLocalMetadata = true; + break; } + + Logger.Debug("{0} returned no metadata for {1}", providerName, item.Path ?? item.Name); } catch (OperationCanceledException) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 641bf0a6a6..fadf4c900f 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -307,6 +307,57 @@ namespace MediaBrowser.Server.Implementations.Dto info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary); + var backropItem = item.HasImage(ImageType.Backdrop) ? item : null; + + var thumbItem = item.HasImage(ImageType.Thumb) ? item : null; + + if (thumbItem == null) + { + var episode = item as Episode; + + if (episode != null) + { + var series = episode.Series; + + if (series != null && series.HasImage(ImageType.Thumb)) + { + thumbItem = series; + } + } + } + + if (backropItem == null) + { + var episode = item as Episode; + + if (episode != null) + { + var series = episode.Series; + + if (series != null && series.HasImage(ImageType.Backdrop)) + { + backropItem = series; + } + } + } + + if (thumbItem == null) + { + thumbItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Thumb)); + } + + if (thumbItem != null) + { + info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb); + info.ThumbItemId = GetDtoId(thumbItem); + } + + if (thumbItem != null) + { + info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop); + info.BackdropItemId = GetDtoId(backropItem); + } + return info; } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index b190b89475..0b1947d4cf 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -5,6 +5,7 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index ac9b42efb2..a8a4e22378 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -89,34 +89,31 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies // Find movies with their own folders if (isDirectory) { - if (args.Path.IndexOf("[trailers]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) { - return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService); + return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false); } - if (args.Path.IndexOf("[musicvideos]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService); + return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false); } - if (args.Path.IndexOf("[adultvideos]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService); + return FindMovie(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie true diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 2924898693..46d3dcc3f5 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -244,7 +244,7 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// Task{ItemsResult}. Task GetSeasonsAsync(SeasonQuery query); - + /// /// Queries for items /// @@ -354,7 +354,7 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// Task{ItemsResult}. Task GetUpcomingEpisodesAsync(NextUpQuery query); - + /// /// Gets a genre /// @@ -572,18 +572,17 @@ namespace MediaBrowser.Model.ApiClient /// Instructs antoher client to browse to a library item. /// /// The session id. - /// The controlling user id. /// The id of the item to browse to. /// The name of the item to browse to. /// The type of the item to browse to. /// Optional ui context (movies, music, tv, games, etc). The client is free to ignore this. /// Task. - Task SendBrowseCommandAsync(string sessionId, string userId, string itemId, string itemName, string itemType, string context); + Task SendBrowseCommandAsync(string sessionId, string itemId, string itemName, string itemType, string context); /// /// Sends the playstate command async. /// - /// The session id. + /// The session id. /// The request. /// Task. Task SendPlaystateCommandAsync(string sessionId, PlaystateRequest request); @@ -780,7 +779,7 @@ namespace MediaBrowser.Model.ApiClient /// The options. /// System.String. string GetImageUrl(ProgramInfoDto item, ImageOptions options); - + /// /// Gets an image url that can be used to download an image from the api /// @@ -910,7 +909,7 @@ namespace MediaBrowser.Model.ApiClient /// The options. /// System.String. string GetThumbImageUrl(BaseItemDto item, ImageOptions options); - + /// /// Gets the url needed to stream an audio file /// @@ -966,7 +965,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{ChannelInfoDto}. Task GetLiveTvChannelAsync(string id, string userId, CancellationToken cancellationToken); - + /// /// Gets the live tv recordings asynchronous. /// @@ -983,7 +982,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{RecordingInfoDto}. Task GetLiveTvRecordingAsync(string id, string userId, CancellationToken cancellationToken); - + /// /// Gets the live tv recording groups asynchronous. /// @@ -1000,7 +999,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{RecordingGroupDto}. Task GetLiveTvRecordingGroupAsync(string id, string userId, CancellationToken cancellationToken); - + /// /// Gets the live tv timers asynchronous. /// @@ -1065,7 +1064,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task. Task UpdateLiveTvSeriesTimerAsync(SeriesTimerInfoDto timer, CancellationToken cancellationToken); - + /// /// Gets the live tv timer asynchronous. /// @@ -1073,7 +1072,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{TimerInfoDto}. Task GetLiveTvTimerAsync(string id, CancellationToken cancellationToken); - + /// /// Gets the live tv series timers asynchronous. /// @@ -1105,7 +1104,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task. Task CancelLiveTvSeriesTimerAsync(string id, CancellationToken cancellationToken); - + /// /// Deletes the live tv recording asynchronous. /// @@ -1127,7 +1126,7 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{GuideInfo}. Task GetLiveTvGuideInfo(CancellationToken cancellationToken); - + /// /// Gets the default timer information. /// diff --git a/MediaBrowser.Model/Session/BrowseRequest.cs b/MediaBrowser.Model/Session/BrowseRequest.cs index 03241860c8..e2cdcc1b28 100644 --- a/MediaBrowser.Model/Session/BrowseRequest.cs +++ b/MediaBrowser.Model/Session/BrowseRequest.cs @@ -1,6 +1,4 @@  -using System; - namespace MediaBrowser.Model.Session { /// @@ -14,8 +12,6 @@ namespace MediaBrowser.Model.Session /// The type of the item. public string ItemType { get; set; } - public Guid UserId { get; set; } - /// /// Gets or sets the item id. /// @@ -27,7 +23,7 @@ namespace MediaBrowser.Model.Session /// /// The name of the item. public string ItemName { get; set; } - + /// /// Gets or sets the context (Movies, Music, Tv, etc) /// Applicable to genres, studios and persons only because the context of items and artists can be inferred. @@ -44,4 +40,4 @@ namespace MediaBrowser.Model.Session public const string TvShows = "TvShows"; public const string Games = "Games"; } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Session/MessageCommand.cs b/MediaBrowser.Model/Session/MessageCommand.cs index 754c057faa..b028765ed2 100644 --- a/MediaBrowser.Model/Session/MessageCommand.cs +++ b/MediaBrowser.Model/Session/MessageCommand.cs @@ -1,15 +1,12 @@  -using System; namespace MediaBrowser.Model.Session { public class MessageCommand - { - public Guid UserId { get; set; } - + { public string Header { get; set; } - + public string Text { get; set; } public long? TimeoutMs { get; set; } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs index 239fb65729..57f6c37f57 100644 --- a/MediaBrowser.Model/Session/PlayRequest.cs +++ b/MediaBrowser.Model/Session/PlayRequest.cs @@ -1,5 +1,4 @@  -using System; namespace MediaBrowser.Model.Session { /// @@ -7,11 +6,6 @@ namespace MediaBrowser.Model.Session /// public class PlayRequest { - public PlayRequest() - { - - } - /// /// Gets or sets the item ids. /// @@ -29,12 +23,6 @@ namespace MediaBrowser.Model.Session /// /// The play command. public PlayCommand PlayCommand { get; set; } - - /// - /// Gets or sets the play command. - /// - /// The play command. - public Guid UserId { get; set; } } /// @@ -55,4 +43,4 @@ namespace MediaBrowser.Model.Session /// PlayLast } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Session/PlaystateCommand.cs b/MediaBrowser.Model/Session/PlaystateCommand.cs index 68e80c4521..918f4f70f4 100644 --- a/MediaBrowser.Model/Session/PlaystateCommand.cs +++ b/MediaBrowser.Model/Session/PlaystateCommand.cs @@ -1,5 +1,4 @@  -using System; namespace MediaBrowser.Model.Session { /// @@ -35,10 +34,8 @@ namespace MediaBrowser.Model.Session public class PlaystateRequest { - public Guid UserId { get; set; } - public PlaystateCommand Command { get; set; } public long? SeekPositionTicks { get; set; } } -} +} \ No newline at end of file -- cgit v1.2.3