diff options
| author | Luke <luke.pulverenti@gmail.com> | 2017-04-20 23:49:50 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-20 23:49:50 -0400 |
| commit | f525f5a89e68248a81ab7cfdfa044fbe45e51863 (patch) | |
| tree | f029e380a0867d6e8db7895e63d9a69e0cfd426f /MediaBrowser.Api | |
| parent | 5dca8cb077fb544628f62939bbda292d8c91b637 (diff) | |
| parent | b9fe720e736abacc57ffb846e4ce6644bc110f61 (diff) | |
Merge pull request #2591 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.Api')
| -rw-r--r-- | MediaBrowser.Api/ApiEntryPoint.cs | 32 | ||||
| -rw-r--r-- | MediaBrowser.Api/MediaBrowser.Api.csproj | 1 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 48 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/MediaInfoService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/StreamRequest.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/StreamState.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Api/SuggestionsService.cs | 94 | ||||
| -rw-r--r-- | MediaBrowser.Api/TvShowsService.cs | 24 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/PlaystateService.cs | 10 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/UserViewsService.cs | 39 |
13 files changed, 155 insertions, 123 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 37ab123667..a59ab33a97 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -16,6 +16,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.IO; @@ -425,18 +426,6 @@ namespace MediaBrowser.Api { job.ChangeKillTimerIfStarted(); } - - if (!string.IsNullOrWhiteSpace(job.LiveStreamId)) - { - try - { - await _mediaSourceManager.PingLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error closing live stream", ex); - } - } } /// <summary> @@ -829,23 +818,4 @@ namespace MediaBrowser.Api } } } - - /// <summary> - /// Enum TranscodingJobType - /// </summary> - public enum TranscodingJobType - { - /// <summary> - /// The progressive - /// </summary> - Progressive, - /// <summary> - /// The HLS - /// </summary> - Hls, - /// <summary> - /// The dash - /// </summary> - Dash - } } diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index c2c8d1102b..0785b904ae 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -134,6 +134,7 @@ <Compile Include="SearchService.cs" /> <Compile Include="Session\SessionsService.cs" /> <Compile Include="SimilarItemsHelper.cs" /> + <Compile Include="SuggestionsService.cs" /> <Compile Include="System\ActivityLogService.cs" /> <Compile Include="System\ActivityLogWebSocketListener.cs" /> <Compile Include="System\SystemService.cs" /> diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 480508e6ff..699c4bbb2f 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -169,7 +169,7 @@ namespace MediaBrowser.Api.Playback { OpenToken = state.MediaSource.OpenToken - }, false, cancellationTokenSource.Token).ConfigureAwait(false); + }, cancellationTokenSource.Token).ConfigureAwait(false); EncodingHelper.AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.RequestedUrl); diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index bd4442a590..038d762456 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -826,6 +826,11 @@ namespace MediaBrowser.Api.Playback.Hls args += " -ab " + bitrate.Value.ToString(UsCulture); } + if (state.OutputAudioSampleRate.HasValue) + { + args += " -ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture); + } + args += " " + EncodingHelper.GetAudioFilterParam(state, ApiEntryPoint.Instance.GetEncodingOptions(), true); return args; @@ -890,6 +895,11 @@ namespace MediaBrowser.Api.Playback.Hls args += " -copyts"; } + if (!string.IsNullOrEmpty(state.OutputVideoSync)) + { + args += " -vsync " + state.OutputVideoSync; + } + return args; } @@ -932,7 +942,7 @@ namespace MediaBrowser.Api.Playback.Hls } var videoCodec = EncodingHelper.GetVideoEncoder(state, ApiEntryPoint.Instance.GetEncodingOptions()); - var breakOnNonKeyFrames = state.Request.BreakOnNonKeyFrames && string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase); + var breakOnNonKeyFrames = state.EnableBreakOnNonKeyFrames(videoCodec); var breakOnNonKeyFramesArg = breakOnNonKeyFrames ? " -break_non_keyframes 1" : ""; diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 03291670b5..ae049a83a4 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 8b828ddfe8..a813d7a872 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -6,10 +6,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using System; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; @@ -60,6 +57,11 @@ namespace MediaBrowser.Api.Playback.Hls args += " -ab " + bitrate.Value.ToString(UsCulture); } + if (state.OutputAudioSampleRate.HasValue) + { + args += " -ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture); + } + args += " " + EncodingHelper.GetAudioFilterParam(state, ApiEntryPoint.Instance.GetEncodingOptions(), true); return args; @@ -85,36 +87,42 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv - if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) + if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && + !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { args += " -bsf:v h264_mp4toannexb"; } - args += " -flags -global_header"; - return args; } + else + { + var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", + state.SegmentLength.ToString(UsCulture)); - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - state.SegmentLength.ToString(UsCulture)); + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; + var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); + args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg; - var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg; + // Add resolution params, if specified + if (!hasGraphicalSubs) + { + args += EncodingHelper.GetOutputSizeParam(state, codec); + } - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - args += EncodingHelper.GetOutputSizeParam(state, codec); + // This is for internal graphical subs + if (hasGraphicalSubs) + { + args += EncodingHelper.GetGraphicalSubtitleParam(state, codec); + } } - // This is for internal graphical subs - if (hasGraphicalSubs) + args += " -flags -global_header"; + + if (!string.IsNullOrEmpty(state.OutputVideoSync)) { - args += EncodingHelper.GetGraphicalSubtitleParam(state, codec); + args += " -vsync " + state.OutputVideoSync; } - args += " -flags -global_header"; - return args; } diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 0ee0dab300..fcd18bfe47 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -109,7 +109,7 @@ namespace MediaBrowser.Api.Playback { var authInfo = _authContext.GetAuthorizationInfo(Request); - var result = await _mediaSourceManager.OpenLiveStream(request, true, CancellationToken.None).ConfigureAwait(false); + var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var profile = request.DeviceProfile; if (profile == null) diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index d02b4bae63..176b68f375 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -42,7 +42,6 @@ namespace MediaBrowser.Api.Playback public int? SegmentLength { get; set; } public int? MinSegments { get; set; } - public bool BreakOnNonKeyFrames { get; set; } } public class VideoStreamRequest : StreamRequest diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 2f5f6227a9..7f146466d4 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -104,14 +104,6 @@ namespace MediaBrowser.Api.Playback } } - public bool IsSegmentedLiveStream - { - get - { - return TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue; - } - } - public int HlsListSize { get @@ -121,14 +113,12 @@ namespace MediaBrowser.Api.Playback } public string UserAgent { get; set; } - public TranscodingJobType TranscodingType { get; set; } public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType) - : base(logger) + : base(logger, transcodingType) { _mediaSourceManager = mediaSourceManager; _logger = logger; - TranscodingType = transcodingType; } public string MimeType { get; set; } diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs new file mode 100644 index 0000000000..99411ffdcb --- /dev/null +++ b/MediaBrowser.Api/SuggestionsService.cs @@ -0,0 +1,94 @@ +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Services; +using System; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; + +namespace MediaBrowser.Api +{ + [Route("/Users/{UserId}/Suggestions", "GET", Summary = "Gets items based on a query.")] + public class GetSuggestedItems : IReturn<QueryResult<BaseItem>> + { + public string MediaType { get; set; } + public string Type { get; set; } + public string UserId { get; set; } + public bool EnableTotalRecordCount { get; set; } + public int? StartIndex { get; set; } + public int? Limit { get; set; } + + public string[] GetMediaTypes() + { + return (MediaType ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + + public string[] GetIncludeItemTypes() + { + return (Type ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + } + + public class SuggestionsService : BaseApiService + { + private readonly IDtoService _dtoService; + private readonly IAuthorizationContext _authContext; + private readonly IUserManager _userManager; + private readonly ILibraryManager _libraryManager; + + public SuggestionsService(IDtoService dtoService, IAuthorizationContext authContext, IUserManager userManager, ILibraryManager libraryManager) + { + _dtoService = dtoService; + _authContext = authContext; + _userManager = userManager; + _libraryManager = libraryManager; + } + + public async Task<object> Get(GetSuggestedItems request) + { + var result = await GetResultItems(request).ConfigureAwait(false); + + return ToOptimizedResult(result); + } + + private async Task<QueryResult<BaseItemDto>> GetResultItems(GetSuggestedItems request) + { + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; + + var dtoOptions = GetDtoOptions(_authContext, request); + var result = GetItems(request, user, dtoOptions); + + var dtoList = await _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ConfigureAwait(false); + + if (dtoList == null) + { + throw new InvalidOperationException("GetBaseItemDtos returned null"); + } + + return new QueryResult<BaseItemDto> + { + TotalRecordCount = result.TotalRecordCount, + Items = dtoList.ToArray() + }; + } + + private QueryResult<BaseItem> GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions) + { + return _libraryManager.GetItemsResult(new InternalItemsQuery(user) + { + SortBy = new string[] { ItemSortBy.Random }, + MediaTypes = request.GetMediaTypes(), + IncludeItemTypes = request.GetIncludeItemTypes(), + IsVirtualItem = false, + StartIndex = request.StartIndex, + Limit = request.Limit, + DtoOptions = dtoOptions, + EnableTotalRecordCount = request.EnableTotalRecordCount, + Recursive = true + }); + } + } +} diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 43fe74d5fb..126f1c7539 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -199,7 +199,6 @@ namespace MediaBrowser.Api [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } - } [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")] @@ -245,7 +244,6 @@ namespace MediaBrowser.Api [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } - } /// <summary> @@ -427,11 +425,11 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var series = _libraryManager.GetItemById(request.Id) as Series; + var series = GetSeries(request.Id, user); if (series == null) { - throw new ResourceNotFoundException("No series exists with Id " + request.Id); + throw new ResourceNotFoundException("Series not found"); } var seasons = (await series.GetItems(new InternalItemsQuery(user) @@ -455,6 +453,16 @@ namespace MediaBrowser.Api }; } + private Series GetSeries(string seriesId, User user) + { + if (!string.IsNullOrWhiteSpace(seriesId)) + { + return _libraryManager.GetItemById(seriesId) as Series; + } + + return null; + } + public async Task<object> Get(GetEpisodes request) { var user = _userManager.GetUserById(request.UserId); @@ -474,11 +482,11 @@ namespace MediaBrowser.Api } else if (request.Season.HasValue) { - var series = _libraryManager.GetItemById(request.Id) as Series; + var series = GetSeries(request.Id, user); if (series == null) { - throw new ResourceNotFoundException("No series exists with Id " + request.Id); + throw new ResourceNotFoundException("Series not found"); } var season = series.GetSeasons(user).FirstOrDefault(i => i.IndexNumber == request.Season.Value); @@ -494,11 +502,11 @@ namespace MediaBrowser.Api } else { - var series = _libraryManager.GetItemById(request.Id) as Series; + var series = GetSeries(request.Id, user); if (series == null) { - throw new ResourceNotFoundException("No series exists with Id " + request.Id); + throw new ResourceNotFoundException("Series not found"); } episodes = series.GetEpisodes(user); diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 504dd29a73..c4cc90955e 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -109,13 +109,6 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] public bool CanSeek { get; set; } - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "QueueableMediaTypes", Description = "A list of media types that can be queued from this item, comma delimited. Audio,Video,Book,Game", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string QueueableMediaTypes { get; set; } - [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] public int? AudioStreamIndex { get; set; } @@ -292,13 +285,10 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="request">The request.</param> public void Post(OnPlaybackStart request) { - var queueableMediaTypes = request.QueueableMediaTypes ?? string.Empty; - Post(new ReportPlaybackStart { CanSeek = request.CanSeek, ItemId = request.Id, - QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(), MediaSourceId = request.MediaSourceId, AudioStreamIndex = request.AudioStreamIndex, SubtitleStreamIndex = request.SubtitleStreamIndex, diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 715745a7dc..89953c2bd8 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -31,17 +31,6 @@ namespace MediaBrowser.Api.UserLibrary public string PresetViews { get; set; } } - [Route("/Users/{UserId}/SpecialViewOptions", "GET")] - public class GetSpecialViewOptions : IReturn<List<SpecialViewOption>> - { - /// <summary> - /// Gets or sets the user id. - /// </summary> - /// <value>The user id.</value> - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string UserId { get; set; } - } - [Route("/Users/{UserId}/GroupingOptions", "GET")] public class GetGroupingOptions : IReturn<List<SpecialViewOption>> { @@ -114,29 +103,6 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - public async Task<object> Get(GetSpecialViewOptions request) - { - var user = _userManager.GetUserById(request.UserId); - - var views = user.RootFolder - .GetChildren(user, true) - .OfType<ICollectionFolder>() - .Where(IsEligibleForSpecialView) - .ToList(); - - var list = views - .Select(i => new SpecialViewOption - { - Name = i.Name, - Id = i.Id.ToString("N") - - }) - .OrderBy(i => i.Name) - .ToList(); - - return ToOptimizedResult(list); - } - public async Task<object> Get(GetGroupingOptions request) { var user = _userManager.GetUserById(request.UserId); @@ -159,11 +125,6 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(list); } - - private bool IsEligibleForSpecialView(ICollectionFolder view) - { - return UserView.IsEligibleForEnhancedView(view.CollectionType); - } } class SpecialViewOption |
