diff options
14 files changed, 193 insertions, 76 deletions
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 06b99e175..235f18296 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -199,21 +199,21 @@ namespace MediaBrowser.Api.Images return _providerManager.GetRemoteImageProviderInfo(item).ToList(); } - public object Get(GetRemoteImages request) + public async Task<object> Get(GetRemoteImages request) { var item = _libraryManager.GetItemById(request.Id); - return GetRemoteImageResult(item, request); + return await GetRemoteImageResult(item, request).ConfigureAwait(false); } - public object Get(GetItemByNameRemoteImages request) + public async Task<object> Get(GetItemByNameRemoteImages request) { var pathInfo = PathInfo.Parse(Request.PathInfo); var type = pathInfo.GetArgumentValue<string>(0); var item = GetItemByName(request.Name, type, _libraryManager); - return GetRemoteImageResult(item, request); + return await GetRemoteImageResult(item, request).ConfigureAwait(false); } private async Task<RemoteImageResult> GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request) @@ -304,7 +304,12 @@ namespace MediaBrowser.Api.Images /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public async Task<object> Get(GetRemoteImage request) + public object Get(GetRemoteImage request) + { + return GetAsync(request).Result; + } + + public async Task<object> GetAsync(GetRemoteImage request) { var urlHash = request.ImageUrl.GetMD5(); var pointerCachePath = GetFullCachePath(urlHash.ToString()); @@ -342,7 +347,7 @@ namespace MediaBrowser.Api.Images return ToStaticFileResult(contentPath); } - + /// <summary> /// Downloads the image. /// </summary> diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs index 8e97e2f3e..e2c10c0c8 100644 --- a/MediaBrowser.Api/Session/SessionsService.cs +++ b/MediaBrowser.Api/Session/SessionsService.cs @@ -297,9 +297,9 @@ namespace MediaBrowser.Api.Session Task.WaitAll(task); } - public Task Post(CreateKey request) + public void Post(CreateKey request) { - return _authRepo.Create(new AuthenticationInfo + var task = _authRepo.Create(new AuthenticationInfo { AppName = request.App, IsActive = true, @@ -307,6 +307,8 @@ namespace MediaBrowser.Api.Session DateCreated = DateTime.UtcNow }, CancellationToken.None); + + Task.WaitAll(task); } public void Post(ReportSessionEnded request) @@ -355,7 +357,7 @@ namespace MediaBrowser.Api.Session return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList()); } - public Task Post(SendPlaystateCommand request) + public void Post(SendPlaystateCommand request) { var command = new PlaystateRequest { @@ -363,14 +365,16 @@ namespace MediaBrowser.Api.Session SeekPositionTicks = request.SeekPositionTicks }; - return _sessionManager.SendPlaystateCommand(GetSession().Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendPlaystateCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> - public Task Post(DisplayContent request) + public void Post(DisplayContent request) { var command = new BrowseRequest { @@ -379,14 +383,16 @@ namespace MediaBrowser.Api.Session ItemType = request.ItemType }; - return _sessionManager.SendBrowseCommand(GetSession().Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendBrowseCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> - public Task Post(SendSystemCommand request) + public void Post(SendSystemCommand request) { GeneralCommandType commandType; var name = request.Command; @@ -404,14 +410,16 @@ namespace MediaBrowser.Api.Session ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null }; - return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> - public Task Post(SendMessageCommand request) + public void Post(SendMessageCommand request) { var command = new MessageCommand { @@ -420,14 +428,16 @@ namespace MediaBrowser.Api.Session Text = request.Text }; - return _sessionManager.SendMessageCommand(GetSession().Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendMessageCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> - public Task Post(Play request) + public void Post(Play request) { var command = new PlayRequest { @@ -437,10 +447,12 @@ namespace MediaBrowser.Api.Session StartPositionTicks = request.StartPositionTicks }; - return _sessionManager.SendPlayCommand(GetSession().Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendPlayCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } - public Task Post(SendGeneralCommand request) + public void Post(SendGeneralCommand request) { var currentSession = GetSession(); @@ -450,16 +462,20 @@ namespace MediaBrowser.Api.Session ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null }; - return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); } - public Task Post(SendFullGeneralCommand request) + public void Post(SendFullGeneralCommand request) { var currentSession = GetSession(); request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null; - return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None); + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None); + + Task.WaitAll(task); } public void Post(AddUserToSession request) diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 16ed0ee29..44b5b0e9b 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -420,8 +420,7 @@ namespace MediaBrowser.Api.UserLibrary var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false); - var dtos = folders.OrderBy(i => i.SortName) - .Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); var result = new QueryResult<BaseItemDto> diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 05a894223..84fcbb91a 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using System; @@ -47,32 +48,54 @@ namespace MediaBrowser.Controller.Playlists inputItems = inputItems.Where(i => i.IsVisible(user)); } - inputItems = inputItems.SelectMany(i => + return inputItems.SelectMany(i => GetPlaylistItems(i, user)) + .Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase)); + } + + private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem i, User user) + { + var musicGenre = i as MusicGenre; + if (musicGenre != null) { - var folder = i as Folder; + var songs = user.RootFolder + .GetRecursiveChildren(user) + .OfType<Audio>() + .Where(a => a.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase)); - if (folder != null) - { - var items = user == null - ? folder.GetRecursiveChildren() - : folder.GetRecursiveChildren(user, true); + return LibraryManager.Sort(songs, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); + } - items = items - .Where(m => !m.IsFolder); + var musicArtist = i as MusicArtist; + if (musicArtist != null) + { + var songs = user.RootFolder + .GetRecursiveChildren(user) + .OfType<Audio>() + .Where(a => a.HasArtist(musicArtist.Name)); - if (!folder.IsPreSorted) - { - items = LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); - } + return LibraryManager.Sort(songs, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); + } + + var folder = i as Folder; - return items; - } + if (folder != null) + { + var items = user == null + ? folder.GetRecursiveChildren() + : folder.GetRecursiveChildren(user, true); + + items = items + .Where(m => !m.IsFolder); - return new[] { i }; + if (!folder.IsPreSorted) + { + items = LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); + } - }).Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase)); + return items; + } - return inputItems; + return new[] { i }; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs index 93d468af0..8d24f6c1f 100644 --- a/MediaBrowser.Controller/Providers/ItemIdentities.cs +++ b/MediaBrowser.Controller/Providers/ItemIdentities.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 5cf4222a8..69fec1e44 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -163,13 +163,13 @@ namespace MediaBrowser.Dlna.Didl if (string.Equals(subtitleMode, "CaptionInfoEx", StringComparison.OrdinalIgnoreCase)) { - var res = container.OwnerDocument.CreateElement("SEC", "CaptionInfoEx"); + //var res = container.OwnerDocument.CreateElement("SEC", "CaptionInfoEx"); - res.InnerText = info.Url; + //res.InnerText = info.Url; - // TODO: attribute needs SEC: - res.SetAttribute("type", info.Format.ToLower()); - container.AppendChild(res); + //// TODO: attribute needs SEC: + //res.SetAttribute("type", info.Format.ToLower()); + //container.AppendChild(res); } else { diff --git a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml index 115ee1b4e..c6ca13e04 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml @@ -2,6 +2,7 @@ <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>DirecTV HD-DVR</Name> <Identification> + <FriendlyName>^DIRECTV.*$</FriendlyName> <Headers> <HttpHeaderInfo name="User-Agent" value="DIRECTV" match="Substring" /> </Headers> diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 4c39c8183..b48018c9a 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -77,6 +77,8 @@ namespace MediaBrowser.Model.Configuration public bool EnableLocalPassword { get; set; } + public string[] OrderedViews { get; set; } + /// <summary> /// Initializes a new instance of the <see cref="UserConfiguration" /> class. /// </summary> @@ -90,6 +92,7 @@ namespace MediaBrowser.Model.Configuration EnableMediaPlayback = true; EnableLiveTvAccess = true; + OrderedViews = new string[] { }; BlockedMediaFolders = new string[] { }; DisplayChannelsWithinViews = new string[] { }; BlockedChannels = new string[] { }; diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 3377d1535..f2ec85cfa 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -342,14 +342,17 @@ namespace MediaBrowser.Providers.Manager if (provider is IRemoteImageProvider || provider is IDynamicImageProvider) { - if (!ConfigurationManager.Configuration.EnableInternetProviders) + if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1) { return false; } - if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1) + if (provider is IRemoteImageProvider) { - return false; + if (!ConfigurationManager.Configuration.EnableInternetProviders) + { + return false; + } } } } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index a2ec897a1..82ccdc4ac 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -5,11 +5,11 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Providers.MediaInfo { diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index acff0231f..97eabcfa9 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -57,11 +57,30 @@ namespace MediaBrowser.Providers.TV { var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb); - if (!string.IsNullOrEmpty(seriesId)) + if (string.IsNullOrEmpty(seriesId)) { + return await FindSeries(searchInfo.Name, cancellationToken).ConfigureAwait(false); } - - return new List<RemoteSearchResult>(); + + var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false); + + var list = new List<RemoteSearchResult>(); + + if (metadata.HasMetadata) + { + var res = new RemoteSearchResult + { + Name = metadata.Item.Name, + PremiereDate = metadata.Item.PremiereDate, + ProductionYear = metadata.Item.ProductionYear, + ProviderIds = metadata.Item.ProviderIds, + SearchProviderName = Name + }; + + list.Add(res); + } + + return list; } public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken) @@ -79,18 +98,13 @@ namespace MediaBrowser.Providers.TV if (string.IsNullOrEmpty(seriesId)) { - seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false); - } + var srch = await GetSearchResults(itemId, cancellationToken).ConfigureAwait(false); - if (string.IsNullOrEmpty(seriesId)) - { - int? yearInName = null; - string nameWithoutYear; - NameParser.ParseName(itemId.Name, out nameWithoutYear, out yearInName); + var entry = srch.FirstOrDefault(); - if (!string.IsNullOrEmpty(nameWithoutYear) && !string.Equals(nameWithoutYear, itemId.Name, StringComparison.OrdinalIgnoreCase)) + if (entry != null) { - seriesId = await FindSeries(nameWithoutYear, cancellationToken).ConfigureAwait(false); + seriesId = entry.GetProviderId(MetadataProviders.Tvdb); } } } @@ -262,8 +276,29 @@ namespace MediaBrowser.Providers.TV /// <param name="name">The name.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.String}.</returns> - private async Task<string> FindSeries(string name, CancellationToken cancellationToken) + private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, CancellationToken cancellationToken) + { + var results = (await FindSeriesInternal(name, cancellationToken).ConfigureAwait(false)).ToList(); + + if (results.Count == 0) + { + int? yearInName = null; + string nameWithoutYear; + NameParser.ParseName(name, out nameWithoutYear, out yearInName); + + if (!string.IsNullOrEmpty(nameWithoutYear) && !string.Equals(nameWithoutYear, name, StringComparison.OrdinalIgnoreCase)) + { + results = (await FindSeriesInternal(nameWithoutYear, cancellationToken).ConfigureAwait(false)).ToList(); + } + } + + return results; + } + + private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, CancellationToken cancellationToken) { + // TODO: Support returning more data, including image url's for the identify function + var url = string.Format(RootUrl + SeriesQuery, WebUtility.UrlEncode(name)); var doc = new XmlDocument(); @@ -278,6 +313,8 @@ namespace MediaBrowser.Providers.TV doc.Load(results); } + var searchResults = new List<RemoteSearchResult>(); + if (doc.HasChildNodes) { var nodes = doc.SelectNodes("//Series"); @@ -305,7 +342,17 @@ namespace MediaBrowser.Providers.TV { var id = node.SelectSingleNode("./seriesid"); if (id != null) - return id.InnerText; + { + var searchResult = new RemoteSearchResult + { + Name = titles.FirstOrDefault(), + SearchProviderName = Name + }; + + searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText); + + searchResults.Add(searchResult); + } } foreach (var title in titles) @@ -317,7 +364,7 @@ namespace MediaBrowser.Providers.TV } _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org."); - return null; + return searchResults; } /// <summary> @@ -1133,11 +1180,20 @@ namespace MediaBrowser.Providers.TV { string tvdbId; if (!info.ProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbId)) - tvdbId = await FindSeries(info.Name, CancellationToken.None); + { + var srch = await GetSearchResults(info, CancellationToken.None).ConfigureAwait(false); + + var entry = srch.FirstOrDefault(); + + if (entry != null) + { + tvdbId = entry.GetProviderId(MetadataProviders.Tvdb); + } + } if (!string.IsNullOrEmpty(tvdbId)) { - return new SeriesIdentity {Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId}; + return new SeriesIdentity { Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId }; } return null; diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs index df122e166..7ffbab860 100644 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs @@ -30,8 +30,8 @@ namespace MediaBrowser.Server.Implementations.Library { var artist = _libraryManager.GetArtist(name); - var genres = _libraryManager.RootFolder - .RecursiveChildren + var genres = user.RootFolder + .GetRecursiveChildren(user) .OfType<Audio>() .Where(i => i.HasArtist(name)) .SelectMany(i => i.Genres) diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index e3ac2025f..63aa3764c 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -133,7 +133,19 @@ namespace MediaBrowser.Server.Implementations.Library } } - return _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).Cast<Folder>(); + var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); + + var orders = user.Configuration.OrderedViews.ToList(); + + return list + .OrderBy(i => + { + var index = orders.IndexOf(i.Id.ToString("N")); + + return index == -1 ? int.MaxValue : index; + }) + .ThenBy(sorted.IndexOf) + .ThenBy(i => i.SortName); } public Task<UserView> GetUserView(string type, User user, string sortName, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 8b392f812..64d6460ee 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1018,5 +1018,7 @@ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", "HeaderPassword": "Password", - "HeaderLocalAccess": "Local Access" + "HeaderLocalAccess": "Local Access", + "HeaderViewOrder": "View Order", + "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps" } |
