diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 435bca0b8c..2e9323e034 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -316,14 +316,14 @@ namespace MediaBrowser.Api
/// The delete files.
/// Task.
/// deviceId
- internal Task KillTranscodingJobs(string deviceId, Func deleteFiles)
+ internal void KillTranscodingJobs(string deviceId, Func deleteFiles)
{
if (string.IsNullOrEmpty(deviceId))
{
throw new ArgumentNullException("deviceId");
}
- return KillTranscodingJobs(j => string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase), deleteFiles);
+ KillTranscodingJobs(j => string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase), deleteFiles);
}
///
@@ -332,7 +332,7 @@ namespace MediaBrowser.Api
/// The kill job.
/// The delete files.
/// Task.
- internal async Task KillTranscodingJobs(Func killJob, Func deleteFiles)
+ internal void KillTranscodingJobs(Func killJob, Func deleteFiles)
{
var jobs = new List();
@@ -348,18 +348,9 @@ namespace MediaBrowser.Api
return;
}
- await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
-
- try
+ foreach (var job in jobs)
{
- foreach (var job in jobs)
- {
- KillTranscodingJob(job, deleteFiles);
- }
- }
- finally
- {
- TranscodingStartLock.Release();
+ KillTranscodingJob(job, deleteFiles);
}
}
@@ -501,7 +492,7 @@ namespace MediaBrowser.Api
}
catch (FileNotFoundException)
{
-
+
}
catch (IOException ex)
{
@@ -563,7 +554,7 @@ namespace MediaBrowser.Api
public long? BytesDownloaded { get; set; }
public long? BytesTranscoded { get; set; }
-
+
public long? TranscodingPositionTicks { get; set; }
public long? DownloadPositionTicks { get; set; }
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index 46b4c06722..ef86a46e8a 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -126,8 +126,14 @@ namespace MediaBrowser.Api.Movies
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
+ var listEligibleForCategories = new List();
+ var listEligibleForSuggestion = new List ();
+
var list = movies.ToList();
+ listEligibleForCategories.AddRange(list);
+ listEligibleForSuggestion.AddRange(list);
+
if (user.Configuration.IncludeTrailersInSuggestions)
{
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
@@ -138,17 +144,20 @@ namespace MediaBrowser.Api.Movies
}, CancellationToken.None).ConfigureAwait(false);
- var newTrailers = trailerResult.Items;
-
- list.AddRange(newTrailers);
-
- list = list
- .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
- .ToList();
+ listEligibleForSuggestion.AddRange(trailerResult.Items);
}
- var result = GetRecommendationCategories(user, list, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList());
+ listEligibleForCategories = listEligibleForCategories
+ .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
+ .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ listEligibleForSuggestion = listEligibleForSuggestion
+ .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
+ .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList());
return ToOptimizedResult(result);
}
@@ -210,11 +219,11 @@ namespace MediaBrowser.Api.Movies
return result;
}
- private IEnumerable GetRecommendationCategories(User user, List allMovies, int categoryLimit, int itemLimit, List fields)
+ private IEnumerable GetRecommendationCategories(User user, List allMoviesForCategories, List allMovies, int categoryLimit, int itemLimit, List fields)
{
var categories = new List();
- var recentlyPlayedMovies = allMovies
+ var recentlyPlayedMovies = allMoviesForCategories
.Select(i =>
{
var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey());
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index cb95049ce1..734b6a9394 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1645,6 +1645,17 @@ namespace MediaBrowser.Api.Playback
{
state.OutputVideoCodec = GetVideoCodec(videoRequest);
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);
+
+ if (state.OutputVideoBitrate.HasValue)
+ {
+ var resolution = ResolutionNormalizer.Normalize(state.OutputVideoBitrate.Value,
+ state.OutputVideoCodec,
+ videoRequest.MaxWidth,
+ videoRequest.MaxHeight);
+
+ videoRequest.MaxWidth = resolution.MaxWidth;
+ videoRequest.MaxHeight = resolution.MaxHeight;
+ }
}
ApplyDeviceProfileSettings(state);
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 2035aff164..b99657c30f 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If the playlist doesn't already exist, startup ffmpeg
try
{
- await ApiEntryPoint.Instance.KillTranscodingJobs(j => j.Type == TranscodingJobType.Hls && string.Equals(j.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase), p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase)).ConfigureAwait(false);
+ ApiEntryPoint.Instance.KillTranscodingJobs(j => j.Type == TranscodingJobType.Hls && string.Equals(j.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase), p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase));
if (currentTranscodingIndex.HasValue)
{
@@ -157,7 +157,7 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
+ await WaitForMinimumSegmentCount(playlistPath, 2, cancellationTokenSource.Token).ConfigureAwait(false);
}
}
}
@@ -402,8 +402,10 @@ namespace MediaBrowser.Api.Playback.Hls
var queryStringIndex = Request.RawUrl.IndexOf('?');
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
+ var isLiveStream = (state.RunTimeTicks ?? 0) == 0;
+
// Main stream
- var playlistUrl = (state.RunTimeTicks ?? 0) > 0 ? "main.m3u8" : "live.m3u8";
+ var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8";
playlistUrl += queryString;
var request = (GetMasterHlsVideoStream)state.Request;
@@ -418,7 +420,7 @@ namespace MediaBrowser.Api.Playback.Hls
AppendPlaylist(builder, playlistUrl, totalBitrate, subtitleGroup);
- if (EnableAdaptiveBitrateStreaming(state))
+ if (EnableAdaptiveBitrateStreaming(state, isLiveStream))
{
var requestedVideoBitrate = state.VideoRequest.VideoBitRate.Value;
@@ -482,7 +484,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
}
- private bool EnableAdaptiveBitrateStreaming(StreamState state)
+ private bool EnableAdaptiveBitrateStreaming(StreamState state, bool isLiveStream)
{
// Within the local network this will likely do more harm than good.
if (Request.IsLocal || NetworkManager.IsInLocalNetwork(Request.RemoteIp))
@@ -491,13 +493,12 @@ namespace MediaBrowser.Api.Playback.Hls
}
var request = state.Request as GetMasterHlsVideoStream;
-
if (request != null && !request.EnableAdaptiveBitrateStreaming)
{
return false;
}
- if (string.IsNullOrWhiteSpace(state.MediaPath))
+ if (isLiveStream || string.IsNullOrWhiteSpace(state.MediaPath))
{
// Opening live streams is so slow it's not even worth it
return false;
diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
index a8d4c6b86f..2263a2b371 100644
--- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
+++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
@@ -72,9 +72,7 @@ namespace MediaBrowser.Api.Playback.Hls
public void Delete(StopEncodingProcess request)
{
- var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true);
-
- Task.WaitAll(task);
+ ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true);
}
///
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
index c2b8069cb2..15a2d5c337 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
@@ -101,7 +102,7 @@ namespace MediaBrowser.Api.UserLibrary
filteredItems = FilterByLibraryItems(request, filteredItems, user, libraryItems);
- filteredItems = ItemsService.ApplySortOrder(request, filteredItems, user, LibraryManager).Cast();
+ filteredItems = LibraryManager.Sort(filteredItems, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending).Cast();
var ibnItemsArray = filteredItems.ToList();
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index f236100147..3dcd4efbda 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -96,6 +96,21 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IsPlayed", Description = "Optional filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsPlayed { get; set; }
+ public string[] GetMediaTypes()
+ {
+ return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public string[] GetIncludeItemTypes()
+ {
+ return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public string[] GetExcludeItemTypes()
+ {
+ return (ExcludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
///
/// Gets the filters.
///
@@ -132,7 +147,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Gets the order by.
///
/// IEnumerable{ItemSortBy}.
- public IEnumerable GetOrderBy()
+ public string[] GetOrderBy()
{
var val = SortBy;
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 2ac4f5e636..011864d35e 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -16,6 +16,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
namespace MediaBrowser.Api.UserLibrary
{
@@ -289,9 +290,9 @@ namespace MediaBrowser.Api.UserLibrary
///
/// The request.
/// System.Object.
- public object Get(GetItems request)
+ public async Task