Przeglądaj źródła

support custom ordering of user views

Luke Pulverenti 10 lat temu
rodzic
commit
b48d15296c

+ 11 - 6
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>

+ 32 - 16
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)

+ 1 - 2
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>

+ 41 - 18
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]

+ 1 - 4
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;
 

+ 5 - 5
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
             {

+ 1 - 0
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>

+ 3 - 0
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[] { };

+ 6 - 3
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;
+                        }
                     }
                 }
             }

+ 1 - 1
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
 {

+ 73 - 17
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;

+ 2 - 2
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)

+ 13 - 1
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)

+ 3 - 1
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"
 }