aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/BaseApiService.cs44
-rw-r--r--MediaBrowser.Api/GamesService.cs21
-rw-r--r--MediaBrowser.Api/Library/FileOrganizationService.cs48
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs70
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj1
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs45
-rw-r--r--MediaBrowser.Api/PackageReviewService.cs2
-rw-r--r--MediaBrowser.Api/PinLoginService.cs202
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs18
-rw-r--r--MediaBrowser.Api/Playback/Dash/MpegDashService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs2
-rw-r--r--MediaBrowser.Api/SearchService.cs2
-rw-r--r--MediaBrowser.Api/StartupWizardService.cs4
-rw-r--r--MediaBrowser.Api/TvShowsService.cs33
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs19
-rw-r--r--MediaBrowser.Api/UserLibrary/UserViewsService.cs23
19 files changed, 411 insertions, 136 deletions
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index c9b1c5c530..c3b0314480 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -183,50 +183,6 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
}
- protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem,bool> filter)
- {
- if (!string.IsNullOrEmpty(parentId))
- {
- var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
-
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return folder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return folder
- .GetRecursiveChildren(filter);
- }
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return userManager
- .GetUserById(userId)
- .RootFolder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return libraryManager
- .RootFolder
- .GetRecursiveChildren(filter);
- }
-
/// <summary>
/// Deslugs an artist name by finding the correct entry in the library
/// </summary>
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index 93cc010793..a27c872f15 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -102,12 +102,16 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public object Get(GetGameSystemSummaries request)
{
- var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is GameSystem)
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(GameSystem).Name }
+ };
+ var parentIds = new string[] { } ;
+ var gameSystems = _libraryManager.GetItems(query, parentIds)
.Cast<GameSystem>()
.ToList();
- var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
-
var result = gameSystems
.Select(i => GetSummary(i, user))
.ToList();
@@ -119,8 +123,15 @@ namespace MediaBrowser.Api
public object Get(GetPlayerIndex request)
{
- var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game)
- .Cast<Game>();
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Game).Name }
+ };
+ var parentIds = new string[] { };
+ var games = _libraryManager.GetItems(query, parentIds)
+ .Cast<Game>()
+ .ToList();
var lookup = games
.ToLookup(i => i.PlayersSupported ?? -1)
diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs
index 29a9826295..1224fa9570 100644
--- a/MediaBrowser.Api/Library/FileOrganizationService.cs
+++ b/MediaBrowser.Api/Library/FileOrganizationService.cs
@@ -1,9 +1,11 @@
-using MediaBrowser.Controller.FileOrganization;
+using System.Collections.Generic;
+using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
namespace MediaBrowser.Api.Library
{
@@ -74,6 +76,31 @@ namespace MediaBrowser.Api.Library
public bool RememberCorrection { get; set; }
}
+ [Route("/Library/FileOrganizations/SmartMatches", "GET", Summary = "Gets smart match entries")]
+ public class GetSmartMatchInfos : IReturn<QueryResult<SmartMatchInfo>>
+ {
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+ }
+
+ [Route("/Library/FileOrganizations/SmartMatches/Delete", "POST", Summary = "Deletes a smart match entry")]
+ public class DeleteSmartMatchEntry
+ {
+ [ApiMember(Name = "Entries", Description = "SmartMatch Entry", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public List<NameValuePair> Entries { get; set; }
+ }
+
[Authenticated(Roles = "Admin")]
public class FileOrganizationService : BaseApiService
{
@@ -130,5 +157,24 @@ namespace MediaBrowser.Api.Library
Task.WaitAll(task);
}
+
+ public object Get(GetSmartMatchInfos request)
+ {
+ var result = _iFileOrganizationService.GetSmartMatchInfos(new FileOrganizationResultQuery
+ {
+ Limit = request.Limit,
+ StartIndex = request.StartIndex
+ });
+
+ return ToOptimizedSerializedResultUsingCache(result);
+ }
+
+ public void Post(DeleteSmartMatchEntry request)
+ {
+ request.Entries.ForEach(entry =>
+ {
+ _iFileOrganizationService.DeleteSmartMatchEntry(entry.Name, entry.Value);
+ });
+ }
}
}
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index b7066a36da..896f8c9908 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -424,7 +424,7 @@ namespace MediaBrowser.Api.Library
public object Get(GetMediaFolders request)
{
- var items = _libraryManager.GetUserRootFolder().Children.OrderBy(i => i.SortName).ToList();
+ var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
if (request.IsHidden.HasValue)
{
@@ -569,7 +569,7 @@ namespace MediaBrowser.Api.Library
{
throw new ArgumentException("This command cannot be used for remote or virtual items.");
}
- if (_fileSystem.DirectoryExists(item.Path))
+ if (_fileSystem.DirectoryExists(item.Path))
{
throw new ArgumentException("This command cannot be used for directories.");
}
@@ -618,7 +618,7 @@ namespace MediaBrowser.Api.Library
var dtoOptions = GetDtoOptions(request);
- BaseItem parent = item.Parent;
+ BaseItem parent = item.GetParent();
while (parent != null)
{
@@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return baseItemDtos.ToList();
@@ -637,7 +637,7 @@ namespace MediaBrowser.Api.Library
private BaseItem TranslateParentItem(BaseItem item, User user)
{
- if (item.Parent is AggregateFolder)
+ if (item.GetParent() is AggregateFolder)
{
return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
}
@@ -685,6 +685,50 @@ namespace MediaBrowser.Api.Library
return ToOptimizedSerializedResultUsingCache(counts);
}
+ private IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter)
+ {
+ if (!string.IsNullOrEmpty(parentId))
+ {
+ var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
+
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return folder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return folder
+ .GetRecursiveChildren(filter);
+ }
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return userManager
+ .GetUserById(userId)
+ .RootFolder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return libraryManager
+ .RootFolder
+ .GetRecursiveChildren(filter);
+ }
+
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{
if (!string.IsNullOrWhiteSpace(userId))
@@ -745,12 +789,10 @@ namespace MediaBrowser.Api.Library
return Task.FromResult(true);
}
- if (item is ILiveTvRecording)
+ return item.Delete(new DeleteOptions
{
- return _liveTv.DeleteRecording(i);
- }
-
- return _libraryManager.DeleteItem(item);
+ DeleteFileLocation = true
+ });
}).ToArray();
Task.WaitAll(tasks);
@@ -847,9 +889,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
@@ -890,9 +932,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 7e55446ae7..f711c69e63 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -80,6 +80,7 @@
<Compile Include="FilterService.cs" />
<Compile Include="IHasDtoOptions.cs" />
<Compile Include="Library\ChapterService.cs" />
+ <Compile Include="PinLoginService.cs" />
<Compile Include="Playback\Dash\ManifestBuilder.cs" />
<Compile Include="Playback\Dash\MpegDashService.cs" />
<Compile Include="Playback\MediaInfoService.cs" />
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index fe8bae1a51..36cbc6ffa6 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarMovies request)
{
var result = await GetSimilarItemsResult(
- // Strip out secondary versions
- request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
-
- SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
+ request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -128,10 +125,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarTrailers request)
{
var result = await GetSimilarItemsResult(
- // Strip out secondary versions
- request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
-
- SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
+ request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -140,8 +134,12 @@ namespace MediaBrowser.Api.Movies
{
var user = _userManager.GetUserById(request.UserId);
- IEnumerable<BaseItem> movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Movie);
-
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Movie).Name }
+ };
+ var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
+ var movies = _libraryManager.GetItems(query, parentIds);
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
var listEligibleForCategories = new List<BaseItem>();
@@ -184,21 +182,27 @@ namespace MediaBrowser.Api.Movies
return ToOptimizedResult(result);
}
- private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
+ private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
{
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var item = string.IsNullOrEmpty(request.Id) ?
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
- Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
-
- var inputItems = user == null
- ? _libraryManager.RootFolder.GetRecursiveChildren(filter)
- : user.RootFolder.GetRecursiveChildren(user, filter);
-
- var list = inputItems.ToList();
+
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Movie).Name }
+ };
+ var parentIds = new string[] { };
+ var list = _libraryManager.GetItems(query, parentIds)
+ .Where(i =>
+ {
+ // Strip out secondary versions
+ var v = i as Video;
+ return v != null && !v.PrimaryVersionId.HasValue;
+ })
+ .ToList();
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
{
@@ -379,9 +383,10 @@ namespace MediaBrowser.Api.Movies
{
foreach (var name in names)
{
- var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery
+ var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
{
Person = name
+
});
var items = allMovies
diff --git a/MediaBrowser.Api/PackageReviewService.cs b/MediaBrowser.Api/PackageReviewService.cs
index b4656b83ee..e70d6a713c 100644
--- a/MediaBrowser.Api/PackageReviewService.cs
+++ b/MediaBrowser.Api/PackageReviewService.cs
@@ -102,7 +102,7 @@ namespace MediaBrowser.Api
{
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _serializer;
- private const string MbAdminUrl = "http://www.mb3admin.com/admin/";
+ private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
private readonly IServerApplicationHost _appHost;
public PackageReviewService(IHttpClient httpClient, IJsonSerializer serializer, IServerApplicationHost appHost)
diff --git a/MediaBrowser.Api/PinLoginService.cs b/MediaBrowser.Api/PinLoginService.cs
new file mode 100644
index 0000000000..8b63de10a5
--- /dev/null
+++ b/MediaBrowser.Api/PinLoginService.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections.Concurrent;
+using System.Globalization;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Model.Connect;
+using ServiceStack;
+
+namespace MediaBrowser.Api
+{
+ [Route("/Auth/Pin", "POST", Summary = "Creates a pin request")]
+ public class CreatePinRequest : IReturn<PinCreationResult>
+ {
+ [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string DeviceId { get; set; }
+ }
+
+ [Route("/Auth/Pin", "GET", Summary = "Gets pin status")]
+ public class GetPinStatusRequest : IReturn<PinStatusResult>
+ {
+ [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string DeviceId { get; set; }
+ [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string Pin { get; set; }
+ }
+
+ [Route("/Auth/Pin/Exchange", "POST", Summary = "Exchanges a pin")]
+ public class ExchangePinRequest : IReturn<PinExchangeResult>
+ {
+ [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string DeviceId { get; set; }
+ [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string Pin { get; set; }
+ }
+
+ [Route("/Auth/Pin/Validate", "POST", Summary = "Validates a pin")]
+ [Authenticated]
+ public class ValidatePinRequest : IReturnVoid
+ {
+ [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string Pin { get; set; }
+ }
+
+ public class PinLoginService : BaseApiService
+ {
+ private readonly ConcurrentDictionary<string, MyPinStatus> _activeRequests = new ConcurrentDictionary<string, MyPinStatus>(StringComparer.OrdinalIgnoreCase);
+
+ public object Post(CreatePinRequest request)
+ {
+ var pin = GetNewPin();
+
+ var value = new MyPinStatus
+ {
+ CreationTimeUtc = DateTime.UtcNow,
+ IsConfirmed = false,
+ IsExpired = false,
+ Pin = pin,
+ DeviceId = request.DeviceId
+ };
+
+ _activeRequests.AddOrUpdate(pin, value, (k, v) => value);
+
+ return ToOptimizedResult(new PinCreationResult
+ {
+ DeviceId = request.DeviceId,
+ IsConfirmed = false,
+ IsExpired = false,
+ Pin = pin
+ });
+ }
+
+ public object Get(GetPinStatusRequest request)
+ {
+ MyPinStatus status;
+
+ if (!_activeRequests.TryGetValue(request.Pin, out status))
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ EnsureValid(request.DeviceId, status);
+
+ return ToOptimizedResult(new PinStatusResult
+ {
+ Pin = status.Pin,
+ IsConfirmed = status.IsConfirmed,
+ IsExpired = status.IsExpired
+ });
+ }
+
+ public object Post(ExchangePinRequest request)
+ {
+ MyPinStatus status;
+
+ if (!_activeRequests.TryGetValue(request.Pin, out status))
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ EnsureValid(request.DeviceId, status);
+
+ if (!status.IsConfirmed)
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ return ToOptimizedResult(new PinExchangeResult
+ {
+ // TODO: Add access token
+ UserId = status.UserId
+ });
+ }
+
+ public void Post(ValidatePinRequest request)
+ {
+ MyPinStatus status;
+
+ if (!_activeRequests.TryGetValue(request.Pin, out status))
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ EnsureValid(status);
+
+ status.IsConfirmed = true;
+ status.UserId = AuthorizationContext.GetAuthorizationInfo(Request).UserId;
+ }
+
+ private void EnsureValid(string requestedDeviceId, MyPinStatus status)
+ {
+ if (!string.Equals(requestedDeviceId, status.DeviceId, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new ResourceNotFoundException();
+ }
+
+ EnsureValid(status);
+ }
+
+ private void EnsureValid(MyPinStatus status)
+ {
+ if ((DateTime.UtcNow - status.CreationTimeUtc).TotalMinutes > 10)
+ {
+ status.IsExpired = true;
+ }
+
+ if (status.IsExpired)
+ {
+ throw new ResourceNotFoundException();
+ }
+ }
+
+ private string GetNewPin()
+ {
+ var pin = GetNewPinInternal();
+
+ while (IsPinActive(pin))
+ {
+ pin = GetNewPinInternal();
+ }
+
+ return pin;
+ }
+
+ private string GetNewPinInternal()
+ {
+ var length = 5;
+ var pin = string.Empty;
+
+ while (pin.Length < length)
+ {
+ var digit = new Random().Next(0, 9);
+ pin += digit.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return pin;
+ }
+
+ private bool IsPinActive(string pin)
+ {
+ MyPinStatus status;
+
+ if (!_activeRequests.TryGetValue(pin, out status))
+ {
+ return true;
+ }
+
+ if (status.IsExpired)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public class MyPinStatus : PinStatusResult
+ {
+ public DateTime CreationTimeUtc { get; set; }
+ public string DeviceId { get; set; }
+ public string UserId { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index bb7f6bb1e9..bae8074fd4 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -305,9 +305,8 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="state">The state.</param>
/// <param name="videoCodec">The video codec.</param>
- /// <param name="isHls">if set to <c>true</c> [is HLS].</param>
/// <returns>System.String.</returns>
- protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
+ protected string GetVideoQualityParam(StreamState state, string videoCodec)
{
var param = string.Empty;
@@ -385,7 +384,7 @@ namespace MediaBrowser.Api.Playback
param = "-mbd 2";
}
- param += GetVideoBitrateParam(state, videoCodec, isHls);
+ param += GetVideoBitrateParam(state, videoCodec);
var framerate = GetFramerateParam(state);
if (framerate.HasValue)
@@ -1190,7 +1189,7 @@ namespace MediaBrowser.Api.Playback
return bitrate;
}
- protected string GetVideoBitrateParam(StreamState state, string videoCodec, bool isHls)
+ protected string GetVideoBitrateParam(StreamState state, string videoCodec)
{
var bitrate = state.OutputVideoBitrate;
@@ -1209,14 +1208,9 @@ namespace MediaBrowser.Api.Playback
}
// h264
- if (isHls)
- {
- return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
- bitrate.Value.ToString(UsCulture),
- (bitrate.Value * 2).ToString(UsCulture));
- }
-
- return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
+ return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
+ bitrate.Value.ToString(UsCulture),
+ (bitrate.Value * 2).ToString(UsCulture));
}
return string.Empty;
diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
index 9ec16fcc78..defb2eef0d 100644
--- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
+++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
@@ -430,7 +430,7 @@ namespace MediaBrowser.Api.Playback.Dash
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg;
+ args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index baf662c34c..4a83615b4d 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -822,7 +822,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg;
+ args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
//args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index be1db1a4df..22c38009a6 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -106,7 +106,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg;
+ args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 19e568ec47..eaf65bd6b6 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -166,7 +166,7 @@ namespace MediaBrowser.Api.Playback.Progressive
args += GetOutputSizeParam(state, videoCodec);
}
- var qualityParam = GetVideoQualityParam(state, videoCodec, false);
+ var qualityParam = GetVideoQualityParam(state, videoCodec);
if (!string.IsNullOrEmpty(qualityParam))
{
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index 602119d4f5..89fc29f3df 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -284,7 +284,7 @@ namespace MediaBrowser.Api
private T GetParentWithImage<T>(BaseItem item, ImageType type)
where T : BaseItem
{
- return item.Parents.OfType<T>().FirstOrDefault(i => i.HasImage(type));
+ return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
}
}
}
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
index b05a1bd209..06db1de745 100644
--- a/MediaBrowser.Api/StartupWizardService.cs
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -66,12 +66,8 @@ namespace MediaBrowser.Api
{
_config.Configuration.IsStartupWizardCompleted = true;
_config.Configuration.EnableLocalizedGuids = true;
- _config.Configuration.EnableLibraryMetadataSubFolder = true;
_config.Configuration.EnableCustomPathSubFolders = true;
- _config.Configuration.DisableStartupScan = true;
- _config.Configuration.EnableUserViews = true;
_config.Configuration.EnableDateLastRefresh = true;
- _config.Configuration.MergeMetadataAndImagesByName = true;
_config.SaveConfiguration();
}
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index 29a4a8bb53..2dad9533fe 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -159,7 +159,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string StartItemId { get; set; }
-
+
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
@@ -273,29 +273,28 @@ namespace MediaBrowser.Api
{
var user = _userManager.GetUserById(request.UserId);
- var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode);
-
- var itemsList = _libraryManager
- .Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending)
- .Cast<Episode>()
- .ToList();
-
- var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList();
-
var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime();
- var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList();
- previousEpisodes.AddRange(unairedEpisodes);
+ var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
- var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit);
+ var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Episode).Name },
+ SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
+ SortOrder = SortOrder.Ascending,
+ MinPremiereDate = minPremiereDate,
+ StartIndex = request.StartIndex,
+ Limit = request.Limit
+
+ }, parentIds);
var options = GetDtoOptions(request);
- var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray();
+ var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
var result = new ItemsResult
{
- TotalRecordCount = itemsList.Count,
+ TotalRecordCount = itemsResult.TotalRecordCount,
Items = returnItems
};
@@ -440,7 +439,7 @@ namespace MediaBrowser.Api
}
episodes = season.GetEpisodes(user);
- }
+ }
else if (request.Season.HasValue)
{
var series = _libraryManager.GetItemById(request.Id) as Series;
@@ -495,7 +494,7 @@ namespace MediaBrowser.Api
.ToList();
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
-
+
var dtoOptions = GetDtoOptions(request);
var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user)
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index 23d4da60c3..6867f6308c 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -206,6 +206,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; }
+ public string GenreIds { get; set; }
+
[ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string OfficialRatings { get; set; }
@@ -385,6 +387,11 @@ namespace MediaBrowser.Api.UserLibrary
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
+ public string[] GetGenreIds()
+ {
+ return (GenreIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
public string[] GetPersonTypes()
{
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 97d0ad7ab0..761d107603 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -112,6 +112,15 @@ namespace MediaBrowser.Api.UserLibrary
user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem;
+ if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
+ {
+ item = user == null ? _libraryManager.RootFolder : user.RootFolder;
+ }
+ else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
+ {
+ item = user == null ? _libraryManager.RootFolder : user.RootFolder;
+ }
+
// Default list type = children
if (!string.IsNullOrEmpty(request.Ids))
@@ -211,6 +220,7 @@ namespace MediaBrowser.Api.UserLibrary
Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(),
+ GenreIds = request.GetGenreIds(),
Studios = request.GetStudios(),
StudioIds = request.GetStudioIds(),
Person = request.Person,
@@ -423,15 +433,6 @@ namespace MediaBrowser.Api.UserLibrary
return false;
}
- // Min index number
- if (request.MinIndexNumber.HasValue)
- {
- if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
- {
- return false;
- }
- }
-
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
index 9d7c38d6f0..d29191db40 100644
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
@@ -26,6 +26,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
public bool? IncludeExternalContent { get; set; }
+
+ public string PresetViews { get; set; }
}
[Route("/Users/{UserId}/SpecialViewOptions", "GET")]
@@ -75,9 +77,24 @@ namespace MediaBrowser.Api.UserLibrary
query.IncludeExternalContent = request.IncludeExternalContent.Value;
}
+ if (!string.IsNullOrWhiteSpace(request.PresetViews))
+ {
+ query.PresetViews = request.PresetViews.Split(',');
+ }
+
+ var app = AuthorizationContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
+ if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
+ }
+ //query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
+
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
var dtoOptions = GetDtoOptions(request);
+ dtoOptions.Fields = new List<ItemFields>();
+ dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
+ dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);
var user = _userManager.GetUserById(request.UserId);
@@ -123,7 +140,7 @@ namespace MediaBrowser.Api.UserLibrary
var views = user.RootFolder
.GetChildren(user, true)
.OfType<Folder>()
- .Where(i => !UserView.IsExcludedFromGrouping(i))
+ .Where(UserView.IsEligibleForGrouping)
.ToList();
var list = views
@@ -141,9 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
private bool IsEligibleForSpecialView(ICollectionFolder view)
{
- var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
-
- return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ return UserView.IsEligibleForEnhancedView(view.CollectionType);
}
}