support custom ordering of user views

This commit is contained in:
Luke Pulverenti 2014-08-18 21:42:53 -04:00
parent 6a2f6782d3
commit b48d15296c
14 changed files with 195 additions and 78 deletions

View File

@ -199,21 +199,21 @@ namespace MediaBrowser.Api.Images
return _providerManager.GetRemoteImageProviderInfo(item).ToList(); return _providerManager.GetRemoteImageProviderInfo(item).ToList();
} }
public object Get(GetRemoteImages request) public async Task<object> Get(GetRemoteImages request)
{ {
var item = _libraryManager.GetItemById(request.Id); 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 pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0); var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager); 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) private async Task<RemoteImageResult> GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request)
@ -304,7 +304,12 @@ namespace MediaBrowser.Api.Images
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <returns>System.Object.</returns> /// <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 urlHash = request.ImageUrl.GetMD5();
var pointerCachePath = GetFullCachePath(urlHash.ToString()); var pointerCachePath = GetFullCachePath(urlHash.ToString());
@ -342,7 +347,7 @@ namespace MediaBrowser.Api.Images
return ToStaticFileResult(contentPath); return ToStaticFileResult(contentPath);
} }
/// <summary> /// <summary>
/// Downloads the image. /// Downloads the image.
/// </summary> /// </summary>

View File

@ -297,9 +297,9 @@ namespace MediaBrowser.Api.Session
Task.WaitAll(task); 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, AppName = request.App,
IsActive = true, IsActive = true,
@ -307,6 +307,8 @@ namespace MediaBrowser.Api.Session
DateCreated = DateTime.UtcNow DateCreated = DateTime.UtcNow
}, CancellationToken.None); }, CancellationToken.None);
Task.WaitAll(task);
} }
public void Post(ReportSessionEnded request) public void Post(ReportSessionEnded request)
@ -355,7 +357,7 @@ namespace MediaBrowser.Api.Session
return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList()); return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList());
} }
public Task Post(SendPlaystateCommand request) public void Post(SendPlaystateCommand request)
{ {
var command = new PlaystateRequest var command = new PlaystateRequest
{ {
@ -363,14 +365,16 @@ namespace MediaBrowser.Api.Session
SeekPositionTicks = request.SeekPositionTicks 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> /// <summary>
/// Posts the specified request. /// Posts the specified request.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
public Task Post(DisplayContent request) public void Post(DisplayContent request)
{ {
var command = new BrowseRequest var command = new BrowseRequest
{ {
@ -379,14 +383,16 @@ namespace MediaBrowser.Api.Session
ItemType = request.ItemType 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> /// <summary>
/// Posts the specified request. /// Posts the specified request.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
public Task Post(SendSystemCommand request) public void Post(SendSystemCommand request)
{ {
GeneralCommandType commandType; GeneralCommandType commandType;
var name = request.Command; var name = request.Command;
@ -404,14 +410,16 @@ namespace MediaBrowser.Api.Session
ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null 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> /// <summary>
/// Posts the specified request. /// Posts the specified request.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
public Task Post(SendMessageCommand request) public void Post(SendMessageCommand request)
{ {
var command = new MessageCommand var command = new MessageCommand
{ {
@ -420,14 +428,16 @@ namespace MediaBrowser.Api.Session
Text = request.Text 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> /// <summary>
/// Posts the specified request. /// Posts the specified request.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
public Task Post(Play request) public void Post(Play request)
{ {
var command = new PlayRequest var command = new PlayRequest
{ {
@ -437,10 +447,12 @@ namespace MediaBrowser.Api.Session
StartPositionTicks = request.StartPositionTicks 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(); var currentSession = GetSession();
@ -450,16 +462,20 @@ namespace MediaBrowser.Api.Session
ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null 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(); var currentSession = GetSession();
request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null; 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) public void Post(AddUserToSession request)

View File

@ -420,8 +420,7 @@ namespace MediaBrowser.Api.UserLibrary
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false); var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
var dtos = folders.OrderBy(i => i.SortName) var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToArray(); .ToArray();
var result = new QueryResult<BaseItemDto> var result = new QueryResult<BaseItemDto>

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using System; using System;
@ -47,32 +48,54 @@ namespace MediaBrowser.Controller.Playlists
inputItems = inputItems.Where(i => i.IsVisible(user)); 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) return LibraryManager.Sort(songs, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
}
var musicArtist = i as MusicArtist;
if (musicArtist != null)
{
var songs = user.RootFolder
.GetRecursiveChildren(user)
.OfType<Audio>()
.Where(a => a.HasArtist(musicArtist.Name));
return LibraryManager.Sort(songs, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
}
var folder = i as Folder;
if (folder != null)
{
var items = user == null
? folder.GetRecursiveChildren()
: folder.GetRecursiveChildren(user, true);
items = items
.Where(m => !m.IsFolder);
if (!folder.IsPreSorted)
{ {
var items = user == null items = LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
? folder.GetRecursiveChildren()
: folder.GetRecursiveChildren(user, true);
items = items
.Where(m => !m.IsFolder);
if (!folder.IsPreSorted)
{
items = LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
}
return items;
} }
return new[] { i }; return items;
}
}).Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase)); return new[] { i };
return inputItems;
} }
[IgnoreDataMember] [IgnoreDataMember]

View File

@ -1,7 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -163,13 +163,13 @@ namespace MediaBrowser.Dlna.Didl
if (string.Equals(subtitleMode, "CaptionInfoEx", StringComparison.OrdinalIgnoreCase)) 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: //// TODO: attribute needs SEC:
res.SetAttribute("type", info.Format.ToLower()); //res.SetAttribute("type", info.Format.ToLower());
container.AppendChild(res); //container.AppendChild(res);
} }
else else
{ {

View File

@ -2,6 +2,7 @@
<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>DirecTV HD-DVR</Name> <Name>DirecTV HD-DVR</Name>
<Identification> <Identification>
<FriendlyName>^DIRECTV.*$</FriendlyName>
<Headers> <Headers>
<HttpHeaderInfo name="User-Agent" value="DIRECTV" match="Substring" /> <HttpHeaderInfo name="User-Agent" value="DIRECTV" match="Substring" />
</Headers> </Headers>

View File

@ -77,6 +77,8 @@ namespace MediaBrowser.Model.Configuration
public bool EnableLocalPassword { get; set; } public bool EnableLocalPassword { get; set; }
public string[] OrderedViews { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class. /// Initializes a new instance of the <see cref="UserConfiguration" /> class.
/// </summary> /// </summary>
@ -90,6 +92,7 @@ namespace MediaBrowser.Model.Configuration
EnableMediaPlayback = true; EnableMediaPlayback = true;
EnableLiveTvAccess = true; EnableLiveTvAccess = true;
OrderedViews = new string[] { };
BlockedMediaFolders = new string[] { }; BlockedMediaFolders = new string[] { };
DisplayChannelsWithinViews = new string[] { }; DisplayChannelsWithinViews = new string[] { };
BlockedChannels = new string[] { }; BlockedChannels = new string[] { };

View File

@ -342,14 +342,17 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteImageProvider || provider is IDynamicImageProvider) if (provider is IRemoteImageProvider || provider is IDynamicImageProvider)
{ {
if (!ConfigurationManager.Configuration.EnableInternetProviders) if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
{ {
return false; return false;
} }
if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1) if (provider is IRemoteImageProvider)
{ {
return false; if (!ConfigurationManager.Configuration.EnableInternetProviders)
{
return false;
}
} }
} }
} }

View File

@ -5,11 +5,11 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Providers.MediaInfo namespace MediaBrowser.Providers.MediaInfo
{ {

View File

@ -57,11 +57,30 @@ namespace MediaBrowser.Providers.TV
{ {
var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb); 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) public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
@ -79,18 +98,13 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(seriesId)) if (string.IsNullOrEmpty(seriesId))
{ {
seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false); var srch = await GetSearchResults(itemId, cancellationToken).ConfigureAwait(false);
}
if (string.IsNullOrEmpty(seriesId)) var entry = srch.FirstOrDefault();
{
int? yearInName = null;
string nameWithoutYear;
NameParser.ParseName(itemId.Name, out nameWithoutYear, out yearInName);
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="name">The name.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns> /// <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 url = string.Format(RootUrl + SeriesQuery, WebUtility.UrlEncode(name));
var doc = new XmlDocument(); var doc = new XmlDocument();
@ -278,6 +313,8 @@ namespace MediaBrowser.Providers.TV
doc.Load(results); doc.Load(results);
} }
var searchResults = new List<RemoteSearchResult>();
if (doc.HasChildNodes) if (doc.HasChildNodes)
{ {
var nodes = doc.SelectNodes("//Series"); var nodes = doc.SelectNodes("//Series");
@ -305,7 +342,17 @@ namespace MediaBrowser.Providers.TV
{ {
var id = node.SelectSingleNode("./seriesid"); var id = node.SelectSingleNode("./seriesid");
if (id != null) 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) 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."); _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org.");
return null; return searchResults;
} }
/// <summary> /// <summary>
@ -1133,11 +1180,20 @@ namespace MediaBrowser.Providers.TV
{ {
string tvdbId; string tvdbId;
if (!info.ProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out 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)) if (!string.IsNullOrEmpty(tvdbId))
{ {
return new SeriesIdentity {Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId}; return new SeriesIdentity { Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId };
} }
return null; return null;

View File

@ -30,8 +30,8 @@ namespace MediaBrowser.Server.Implementations.Library
{ {
var artist = _libraryManager.GetArtist(name); var artist = _libraryManager.GetArtist(name);
var genres = _libraryManager.RootFolder var genres = user.RootFolder
.RecursiveChildren .GetRecursiveChildren(user)
.OfType<Audio>() .OfType<Audio>()
.Where(i => i.HasArtist(name)) .Where(i => i.HasArtist(name))
.SelectMany(i => i.Genres) .SelectMany(i => i.Genres)

View File

@ -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) public Task<UserView> GetUserView(string type, User user, string sortName, CancellationToken cancellationToken)

View File

@ -1018,5 +1018,7 @@
"LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"HeaderPassword": "Password", "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"
} }