diff options
Diffstat (limited to 'MediaBrowser.Api')
28 files changed, 501 insertions, 185 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 6691080bc..c7485a2e9 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -284,8 +284,8 @@ namespace MediaBrowser.Api Width = state.OutputWidth, Height = state.OutputHeight, AudioChannels = state.OutputAudioChannels, - IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase), - IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase), + IsAudioDirect = EncodingHelper.IsCopyCodec(state.OutputAudioCodec), + IsVideoDirect = EncodingHelper.IsCopyCodec(state.OutputVideoCodec), TranscodeReasons = state.TranscodeReasons }); } diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 1a1d86362..2cd68ac1b 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Api public abstract class BaseApiService : IService, IRequiresRequest { public BaseApiService( - ILogger logger, + ILogger<BaseApiService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory) { @@ -34,7 +34,7 @@ namespace MediaBrowser.Api /// Gets the logger. /// </summary> /// <value>The logger.</value> - protected ILogger Logger { get; } + protected ILogger<BaseApiService> Logger { get; } /// <summary> /// Gets or sets the server configuration manager. diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs index 7004a2559..dd3f3e738 100644 --- a/MediaBrowser.Api/Devices/DeviceService.cs +++ b/MediaBrowser.Api/Devices/DeviceService.cs @@ -1,5 +1,3 @@ -using System.IO; -using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Net; @@ -41,33 +39,6 @@ namespace MediaBrowser.Api.Devices public string Id { get; set; } } - [Route("/Devices/CameraUploads", "GET", Summary = "Gets camera upload history for a device")] - [Authenticated] - public class GetCameraUploads : IReturn<ContentUploadHistory> - { - [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string DeviceId { get; set; } - } - - [Route("/Devices/CameraUploads", "POST", Summary = "Uploads content")] - [Authenticated] - public class PostCameraUpload : IRequiresRequestStream, IReturnVoid - { - [ApiMember(Name = "DeviceId", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string DeviceId { get; set; } - - [ApiMember(Name = "Album", Description = "Album", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Album { get; set; } - - [ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Name { get; set; } - - [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Id { get; set; } - - public Stream RequestStream { get; set; } - } - [Route("/Devices/Options", "POST", Summary = "Updates device options")] [Authenticated(Roles = "Admin")] public class PostDeviceOptions : DeviceOptions, IReturnVoid @@ -116,11 +87,6 @@ namespace MediaBrowser.Api.Devices return _deviceManager.GetDeviceOptions(request.Id); } - public object Get(GetCameraUploads request) - { - return ToOptimizedResult(_deviceManager.GetCameraUploadHistory(request.DeviceId)); - } - public void Delete(DeleteDevice request) { var sessions = _authRepo.Get(new AuthenticationInfoQuery @@ -134,35 +100,5 @@ namespace MediaBrowser.Api.Devices _sessionManager.Logout(session); } } - - public Task Post(PostCameraUpload request) - { - var deviceId = Request.QueryString["DeviceId"]; - var album = Request.QueryString["Album"]; - var id = Request.QueryString["Id"]; - var name = Request.QueryString["Name"]; - var req = Request.Response.HttpContext.Request; - - if (req.HasFormContentType) - { - var file = req.Form.Files.Count == 0 ? null : req.Form.Files[0]; - - return _deviceManager.AcceptCameraUpload(deviceId, file.OpenReadStream(), new LocalFileInfo - { - MimeType = file.ContentType, - Album = album, - Name = name, - Id = id - }); - } - - return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo - { - MimeType = Request.ContentType, - Album = album, - Name = name, - Id = id - }); - } } } diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index d199ce154..82d471412 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -226,12 +226,7 @@ namespace MediaBrowser.Api /// <returns>IEnumerable{FileSystemEntryInfo}.</returns> private IEnumerable<FileSystemEntryInfo> GetDrives() { - return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo - { - Name = d.Name, - Path = d.FullName, - Type = FileSystemEntryType.Directory - }); + return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Directory)); } /// <summary> @@ -261,13 +256,7 @@ namespace MediaBrowser.Api return request.IncludeDirectories || !isDirectory; }); - return entries.Select(f => new FileSystemEntryInfo - { - Name = f.Name, - Path = f.FullName, - Type = f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File - - }); + return entries.Select(f => new FileSystemEntryInfo(f.Name, f.FullName, f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File)); } public object Get(GetParentPath request) diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 2e9b3e6cb..fdb15d96a 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; @@ -280,9 +281,16 @@ namespace MediaBrowser.Api.Images public List<ImageInfo> GetItemImageInfos(BaseItem item) { var list = new List<ImageInfo>(); - var itemImages = item.ImageInfos; + if (itemImages.Length == 0) + { + // short-circuit + return list; + } + + _libraryManager.UpdateImages(item); // this makes sure dimensions and hashes are correct + foreach (var image in itemImages) { if (!item.AllowsMultipleImages(image.Type)) @@ -323,6 +331,7 @@ namespace MediaBrowser.Api.Images { int? width = null; int? height = null; + string blurhash = null; long length = 0; try @@ -332,10 +341,9 @@ namespace MediaBrowser.Api.Images var fileInfo = _fileSystem.GetFileInfo(info.Path); length = fileInfo.Length; - ImageDimensions size = _imageProcessor.GetImageDimensions(item, info); - _libraryManager.UpdateImages(item); - width = size.Width; - height = size.Height; + blurhash = info.BlurHash; + width = info.Width; + height = info.Height; if (width <= 0 || height <= 0) { @@ -358,6 +366,7 @@ namespace MediaBrowser.Api.Images ImageType = info.Type, ImageTag = _imageProcessor.GetImageCacheTag(item, info), Size = length, + BlurHash = blurhash, Width = width, Height = height }; @@ -555,8 +564,7 @@ namespace MediaBrowser.Api.Images var imageInfo = GetImageInfo(request, item); if (imageInfo == null) { - var displayText = item == null ? itemId.ToString() : item.Name; - throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", displayText, request.Type)); + throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type)); } bool cropwhitespace; diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 222bb34d3..358ac30fa 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -147,9 +147,8 @@ namespace MediaBrowser.Api.Images { var item = _libraryManager.GetItemById(request.Id); - var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery + var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery(request.ProviderName) { - ProviderName = request.ProviderName, IncludeAllLanguages = request.IncludeAllLanguages, IncludeDisabledProviders = true, ImageType = request.Type @@ -265,17 +264,20 @@ namespace MediaBrowser.Api.Images { Url = url, BufferContent = false - }).ConfigureAwait(false); - var ext = result.ContentType.Split('/').Last(); + var ext = result.ContentType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); - using (var stream = result.Content) + var stream = result.Content; + await using (stream.ConfigureAwait(false)) { - using var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); - await stream.CopyToAsync(filestream).ConfigureAwait(false); + var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + await using (filestream.ConfigureAwait(false)) + { + await stream.CopyToAsync(filestream).ConfigureAwait(false); + } } Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 0bbe7e1cf..68e3dfa59 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -299,22 +299,26 @@ namespace MediaBrowser.Api { var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false); - var ext = result.ContentType.Split('/').Last(); + var ext = result.ContentType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); - using (var stream = result.Content) + var stream = result.Content; + + await using (stream.ConfigureAwait(false)) { - using var fileStream = new FileStream( + var fileStream = new FileStream( fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); - - await stream.CopyToAsync(fileStream).ConfigureAwait(false); + await using (fileStream.ConfigureAwait(false)) + { + await stream.CopyToAsync(fileStream).ConfigureAwait(false); + } } Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index a54640b2f..c0146dfee 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -319,11 +319,14 @@ namespace MediaBrowser.Api.Library private readonly ILocalizationManager _localization; private readonly ILibraryMonitor _libraryMonitor; + private readonly ILogger<MoviesService> _moviesServiceLogger; + /// <summary> /// Initializes a new instance of the <see cref="LibraryService" /> class. /// </summary> public LibraryService( ILogger<LibraryService> logger, + ILogger<MoviesService> moviesServiceLogger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IProviderManager providerManager, @@ -344,6 +347,7 @@ namespace MediaBrowser.Api.Library _activityManager = activityManager; _localization = localization; _libraryMonitor = libraryMonitor; + _moviesServiceLogger = moviesServiceLogger; } private string[] GetRepresentativeItemTypes(string contentType) @@ -543,7 +547,7 @@ namespace MediaBrowser.Api.Library if (item is Movie || (program != null && program.IsMovie) || item is Trailer) { return new MoviesService( - Logger, + _moviesServiceLogger, ServerConfigurationManager, ResultFactory, _userManager, @@ -759,13 +763,12 @@ namespace MediaBrowser.Api.Library { try { - _activityManager.Create(new ActivityLogEntry + _activityManager.Create(new Jellyfin.Data.Entities.ActivityLog( + string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name), + "UserDownloadingContent", + auth.UserId) { - Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name), - Type = "UserDownloadingContent", ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), - UserId = auth.UserId - }); } catch diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 46da8b909..cdd027634 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Api.Movies /// Initializes a new instance of the <see cref="MoviesService" /> class. /// </summary> public MoviesService( - ILogger logger, + ILogger<MoviesService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 8adf9c621..0b5334235 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -33,13 +33,18 @@ namespace MediaBrowser.Api.Movies /// </summary> private readonly ILibraryManager _libraryManager; + /// <summary> + /// The logger for the created <see cref="ItemsService"/> instances. + /// </summary> + private readonly ILogger<ItemsService> _logger; + private readonly IDtoService _dtoService; private readonly ILocalizationManager _localizationManager; private readonly IJsonSerializer _json; private readonly IAuthorizationContext _authContext; public TrailersService( - ILogger<TrailersService> logger, + ILoggerFactory loggerFactory, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, @@ -48,7 +53,7 @@ namespace MediaBrowser.Api.Movies ILocalizationManager localizationManager, IJsonSerializer json, IAuthorizationContext authContext) - : base(logger, serverConfigurationManager, httpResultFactory) + : base(loggerFactory.CreateLogger<TrailersService>(), serverConfigurationManager, httpResultFactory) { _userManager = userManager; _libraryManager = libraryManager; @@ -56,6 +61,7 @@ namespace MediaBrowser.Api.Movies _localizationManager = localizationManager; _json = json; _authContext = authContext; + _logger = loggerFactory.CreateLogger<ItemsService>(); } public object Get(Getrailers request) @@ -66,7 +72,7 @@ namespace MediaBrowser.Api.Movies getItems.IncludeItemTypes = "Trailer"; return new ItemsService( - Logger, + _logger, ServerConfigurationManager, ResultFactory, _userManager, diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 928ca1612..24297d500 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.Api.Playback /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. /// </summary> protected BaseStreamingService( - ILogger logger, + ILogger<BaseStreamingService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, @@ -193,7 +193,7 @@ namespace MediaBrowser.Api.Playback await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); - if (state.VideoRequest != null && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { var auth = AuthorizationContext.GetAuthorizationInfo(Request); if (auth.User != null && !auth.User.Policy.EnableVideoPlaybackTranscoding) @@ -243,9 +243,9 @@ namespace MediaBrowser.Api.Playback var logFilePrefix = "ffmpeg-transcode"; if (state.VideoRequest != null - && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + && EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { - logFilePrefix = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase) + logFilePrefix = EncodingHelper.IsCopyCodec(state.OutputAudioCodec) ? "ffmpeg-remux" : "ffmpeg-directstream"; } @@ -328,7 +328,7 @@ namespace MediaBrowser.Api.Playback state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo && state.VideoType == VideoType.VideoFile && - !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase); + !EncodingHelper.IsCopyCodec(state.OutputVideoCodec); } return false; @@ -791,7 +791,7 @@ namespace MediaBrowser.Api.Playback EncodingHelper.TryStreamCopy(state); } - if (state.OutputVideoBitrate.HasValue && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (state.OutputVideoBitrate.HasValue && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { var resolution = ResolutionNormalizer.Normalize( state.VideoStream?.BitRate, diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 52962366c..627421aac 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Api.Playback.Hls public abstract class BaseHlsService : BaseStreamingService { public BaseHlsService( - ILogger logger, + ILogger<BaseHlsService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, @@ -209,24 +209,28 @@ namespace MediaBrowser.Api.Playback.Hls try { // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written - using var fileStream = GetPlaylistFileStream(playlist); - using var reader = new StreamReader(fileStream); - var count = 0; - - while (!reader.EndOfStream) + var fileStream = GetPlaylistFileStream(playlist); + await using (fileStream.ConfigureAwait(false)) { - var line = reader.ReadLine(); + using var reader = new StreamReader(fileStream); + var count = 0; - if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) + while (!reader.EndOfStream) { - count++; - if (count >= segmentCount) + var line = await reader.ReadLineAsync().ConfigureAwait(false); + + if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) { - Logger.LogDebug("Finished waiting for {0} segments in {1}", segmentCount, playlist); - return; + count++; + if (count >= segmentCount) + { + Logger.LogDebug("Finished waiting for {0} segments in {1}", segmentCount, playlist); + return; + } } } } + await Task.Delay(100, cancellationToken).ConfigureAwait(false); } catch (IOException) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7f74e85e9..c746cef80 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Api.Playback.Hls public class DynamicHlsService : BaseHlsService { public DynamicHlsService( - ILogger logger, + ILogger<DynamicHlsService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, @@ -700,12 +700,12 @@ namespace MediaBrowser.Api.Playback.Hls return false; } - if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { return false; } - if (string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(state.OutputAudioCodec)) { return false; } @@ -728,7 +728,7 @@ namespace MediaBrowser.Api.Playback.Hls private int? GetOutputVideoCodecLevel(StreamState state) { string levelString; - if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) + if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec) && state.VideoStream.Level.HasValue) { levelString = state.VideoStream?.Level.ToString(); @@ -865,7 +865,7 @@ namespace MediaBrowser.Api.Playback.Hls { framerate = Math.Round(state.TargetFramerate.GetValueOrDefault(), 3); } - else if (state.VideoStream.RealFrameRate.HasValue) + else if (state.VideoStream?.RealFrameRate != null) { framerate = Math.Round(state.VideoStream.RealFrameRate.GetValueOrDefault(), 3); } @@ -1008,7 +1008,7 @@ namespace MediaBrowser.Api.Playback.Hls if (!state.IsOutputVideo) { - if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(audioCodec)) { return "-acodec copy"; } @@ -1036,11 +1036,11 @@ namespace MediaBrowser.Api.Playback.Hls return string.Join(" ", audioTranscodeParams.ToArray()); } - if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(audioCodec)) { var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions); - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.EnableBreakOnNonKeyFrames(videoCodec)) + if (EncodingHelper.IsCopyCodec(videoCodec) && state.EnableBreakOnNonKeyFrames(videoCodec)) { return "-codec:a:0 copy -copypriorss:a:0 0"; } @@ -1091,7 +1091,7 @@ namespace MediaBrowser.Api.Playback.Hls // } // See if we can save come cpu cycles by avoiding encoding - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(codec)) { if (state.VideoStream != null && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index d1c53c1c1..aefb3f019 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Api.Playback.Hls { var codec = EncodingHelper.GetAudioEncoder(state); - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(codec)) { return "-codec:a:0 copy"; } diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index db24eaca6..e2d771ec6 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Api.Playback private readonly IAuthorizationContext _authContext; public MediaInfoService( - ILogger logger, + ILogger<MediaInfoService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IMediaSourceManager mediaSourceManager, diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index 8d1e3a3f2..34c7986ca 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Playback.Progressive public class AudioService : BaseProgressiveStreamingService { public AudioService( - ILogger logger, + ILogger<AudioService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IHttpClient httpClient, diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index ed68219c9..c7bf055fb 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Api.Playback.Progressive protected IHttpClient HttpClient { get; private set; } public BaseProgressiveStreamingService( - ILogger logger, + ILogger<BaseProgressiveStreamingService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IHttpClient httpClient, diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index d5d2f58c0..c244b0033 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Api.Playback return Request.SegmentLength.Value; } - if (string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + if (EncodingHelper.IsCopyCodec(OutputVideoCodec)) { var userAgent = UserAgent ?? string.Empty; diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index cebd4b49a..a3b319d44 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -75,9 +75,11 @@ namespace MediaBrowser.Api.Playback public class UniversalAudioService : BaseApiService { private readonly EncodingHelper _encodingHelper; + private readonly ILoggerFactory _loggerFactory; public UniversalAudioService( ILogger<UniversalAudioService> logger, + ILoggerFactory loggerFactory, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IHttpClient httpClient, @@ -108,6 +110,7 @@ namespace MediaBrowser.Api.Playback AuthorizationContext = authorizationContext; NetworkManager = networkManager; _encodingHelper = encodingHelper; + _loggerFactory = loggerFactory; } protected IHttpClient HttpClient { get; private set; } @@ -233,7 +236,7 @@ namespace MediaBrowser.Api.Playback AuthorizationContext.GetAuthorizationInfo(Request).DeviceId = request.DeviceId; var mediaInfoService = new MediaInfoService( - Logger, + _loggerFactory.CreateLogger<MediaInfoService>(), ServerConfigurationManager, ResultFactory, MediaSourceManager, @@ -277,7 +280,7 @@ namespace MediaBrowser.Api.Playback if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { var service = new DynamicHlsService( - Logger, + _loggerFactory.CreateLogger<DynamicHlsService>(), ServerConfigurationManager, ResultFactory, UserManager, @@ -331,7 +334,7 @@ namespace MediaBrowser.Api.Playback else { var service = new AudioService( - Logger, + _loggerFactory.CreateLogger<AudioService>(), ServerConfigurationManager, ResultFactory, HttpClient, diff --git a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs index d882aac88..175984575 100644 --- a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs @@ -31,48 +31,48 @@ namespace MediaBrowser.Api.Sessions { _sessionManager = sessionManager; - _sessionManager.SessionStarted += _sessionManager_SessionStarted; - _sessionManager.SessionEnded += _sessionManager_SessionEnded; - _sessionManager.PlaybackStart += _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped; - _sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress; - _sessionManager.CapabilitiesChanged += _sessionManager_CapabilitiesChanged; - _sessionManager.SessionActivity += _sessionManager_SessionActivity; + _sessionManager.SessionStarted += OnSessionManagerSessionStarted; + _sessionManager.SessionEnded += OnSessionManagerSessionEnded; + _sessionManager.PlaybackStart += OnSessionManagerPlaybackStart; + _sessionManager.PlaybackStopped += OnSessionManagerPlaybackStopped; + _sessionManager.PlaybackProgress += OnSessionManagerPlaybackProgress; + _sessionManager.CapabilitiesChanged += OnSessionManagerCapabilitiesChanged; + _sessionManager.SessionActivity += OnSessionManagerSessionActivity; } - void _sessionManager_SessionActivity(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionActivity(object sender, SessionEventArgs e) { - SendData(false); + await SendData(false).ConfigureAwait(false); } - void _sessionManager_CapabilitiesChanged(object sender, SessionEventArgs e) + private async void OnSessionManagerCapabilitiesChanged(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackProgress(object sender, PlaybackProgressEventArgs e) { - SendData(!e.IsAutomated); + await SendData(!e.IsAutomated).ConfigureAwait(false); } - void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) + private async void OnSessionManagerPlaybackStopped(object sender, PlaybackStopEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackStart(object sender, PlaybackProgressEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - void _sessionManager_SessionEnded(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionStarted(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } /// <summary> @@ -84,15 +84,16 @@ namespace MediaBrowser.Api.Sessions return Task.FromResult(_sessionManager.Sessions); } + /// <inheritdoc /> protected override void Dispose(bool dispose) { - _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - _sessionManager.SessionEnded -= _sessionManager_SessionEnded; - _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped; - _sessionManager.PlaybackProgress -= _sessionManager_PlaybackProgress; - _sessionManager.CapabilitiesChanged -= _sessionManager_CapabilitiesChanged; - _sessionManager.SessionActivity -= _sessionManager_SessionActivity; + _sessionManager.SessionStarted -= OnSessionManagerSessionStarted; + _sessionManager.SessionEnded -= OnSessionManagerSessionEnded; + _sessionManager.PlaybackStart -= OnSessionManagerPlaybackStart; + _sessionManager.PlaybackStopped -= OnSessionManagerPlaybackStopped; + _sessionManager.PlaybackProgress -= OnSessionManagerPlaybackProgress; + _sessionManager.CapabilitiesChanged -= OnSessionManagerCapabilitiesChanged; + _sessionManager.SessionActivity -= OnSessionManagerSessionActivity; base.Dispose(dispose); } diff --git a/MediaBrowser.Api/SyncPlay/SyncPlayService.cs b/MediaBrowser.Api/SyncPlay/SyncPlayService.cs new file mode 100644 index 000000000..1e14ea552 --- /dev/null +++ b/MediaBrowser.Api/SyncPlay/SyncPlayService.cs @@ -0,0 +1,302 @@ +using System.Threading; +using System; +using System.Collections.Generic; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Session; +using MediaBrowser.Controller.SyncPlay; +using MediaBrowser.Model.Services; +using MediaBrowser.Model.SyncPlay; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Api.SyncPlay +{ + [Route("/SyncPlay/{SessionId}/NewGroup", "POST", Summary = "Create a new SyncPlay group")] + [Authenticated] + public class SyncPlayNewGroup : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/JoinGroup", "POST", Summary = "Join an existing SyncPlay group")] + [Authenticated] + public class SyncPlayJoinGroup : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + + /// <summary> + /// Gets or sets the Group id. + /// </summary> + /// <value>The Group id to join.</value> + [ApiMember(Name = "GroupId", Description = "Group Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string GroupId { get; set; } + + /// <summary> + /// Gets or sets the playing item id. + /// </summary> + /// <value>The client's currently playing item id.</value> + [ApiMember(Name = "PlayingItemId", Description = "Client's playing item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string PlayingItemId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/LeaveGroup", "POST", Summary = "Leave joined SyncPlay group")] + [Authenticated] + public class SyncPlayLeaveGroup : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/ListGroups", "POST", Summary = "List SyncPlay groups")] + [Authenticated] + public class SyncPlayListGroups : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + + /// <summary> + /// Gets or sets the filter item id. + /// </summary> + /// <value>The filter item id.</value> + [ApiMember(Name = "FilterItemId", Description = "Filter by item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string FilterItemId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/PlayRequest", "POST", Summary = "Request play in SyncPlay group")] + [Authenticated] + public class SyncPlayPlayRequest : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/PauseRequest", "POST", Summary = "Request pause in SyncPlay group")] + [Authenticated] + public class SyncPlayPauseRequest : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + } + + [Route("/SyncPlay/{SessionId}/SeekRequest", "POST", Summary = "Request seek in SyncPlay group")] + [Authenticated] + public class SyncPlaySeekRequest : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + + [ApiMember(Name = "PositionTicks", IsRequired = true, DataType = "long", ParameterType = "query", Verb = "POST")] + public long PositionTicks { get; set; } + } + + [Route("/SyncPlay/{SessionId}/BufferingRequest", "POST", Summary = "Request group wait in SyncPlay group while buffering")] + [Authenticated] + public class SyncPlayBufferingRequest : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + + /// <summary> + /// Gets or sets the date used to pin PositionTicks in time. + /// </summary> + /// <value>The date related to PositionTicks.</value> + [ApiMember(Name = "When", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string When { get; set; } + + [ApiMember(Name = "PositionTicks", IsRequired = true, DataType = "long", ParameterType = "query", Verb = "POST")] + public long PositionTicks { get; set; } + + /// <summary> + /// Gets or sets whether this is a buffering or a buffering-done request. + /// </summary> + /// <value><c>true</c> if buffering is complete; <c>false</c> otherwise.</value> + [ApiMember(Name = "BufferingDone", IsRequired = true, DataType = "bool", ParameterType = "query", Verb = "POST")] + public bool BufferingDone { get; set; } + } + + [Route("/SyncPlay/{SessionId}/UpdatePing", "POST", Summary = "Update session ping")] + [Authenticated] + public class SyncPlayUpdatePing : IReturnVoid + { + [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SessionId { get; set; } + + [ApiMember(Name = "Ping", IsRequired = true, DataType = "double", ParameterType = "query", Verb = "POST")] + public double Ping { get; set; } + } + + /// <summary> + /// Class SyncPlayService. + /// </summary> + public class SyncPlayService : BaseApiService + { + /// <summary> + /// The session context. + /// </summary> + private readonly ISessionContext _sessionContext; + + /// <summary> + /// The SyncPlay manager. + /// </summary> + private readonly ISyncPlayManager _syncPlayManager; + + public SyncPlayService( + ILogger<SyncPlayService> logger, + IServerConfigurationManager serverConfigurationManager, + IHttpResultFactory httpResultFactory, + ISessionContext sessionContext, + ISyncPlayManager syncPlayManager) + : base(logger, serverConfigurationManager, httpResultFactory) + { + _sessionContext = sessionContext; + _syncPlayManager = syncPlayManager; + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayNewGroup request) + { + var currentSession = GetSession(_sessionContext); + _syncPlayManager.NewGroup(currentSession, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayJoinGroup request) + { + var currentSession = GetSession(_sessionContext); + + Guid groupId; + Guid playingItemId = Guid.Empty; + + if (!Guid.TryParse(request.GroupId, out groupId)) + { + Logger.LogError("JoinGroup: {0} is not a valid format for GroupId. Ignoring request.", request.GroupId); + return; + } + + // Both null and empty strings mean that client isn't playing anything + if (!string.IsNullOrEmpty(request.PlayingItemId) && !Guid.TryParse(request.PlayingItemId, out playingItemId)) + { + Logger.LogError("JoinGroup: {0} is not a valid format for PlayingItemId. Ignoring request.", request.PlayingItemId); + return; + } + + var joinRequest = new JoinGroupRequest() + { + GroupId = groupId, + PlayingItemId = playingItemId + }; + + _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayLeaveGroup request) + { + var currentSession = GetSession(_sessionContext); + _syncPlayManager.LeaveGroup(currentSession, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <value>The requested list of groups.</value> + public List<GroupInfoView> Post(SyncPlayListGroups request) + { + var currentSession = GetSession(_sessionContext); + var filterItemId = Guid.Empty; + + if (!string.IsNullOrEmpty(request.FilterItemId) && !Guid.TryParse(request.FilterItemId, out filterItemId)) + { + Logger.LogWarning("ListGroups: {0} is not a valid format for FilterItemId. Ignoring filter.", request.FilterItemId); + } + + return _syncPlayManager.ListGroups(currentSession, filterItemId); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayPlayRequest request) + { + var currentSession = GetSession(_sessionContext); + var syncPlayRequest = new PlaybackRequest() + { + Type = PlaybackRequestType.Play + }; + _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayPauseRequest request) + { + var currentSession = GetSession(_sessionContext); + var syncPlayRequest = new PlaybackRequest() + { + Type = PlaybackRequestType.Pause + }; + _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlaySeekRequest request) + { + var currentSession = GetSession(_sessionContext); + var syncPlayRequest = new PlaybackRequest() + { + Type = PlaybackRequestType.Seek, + PositionTicks = request.PositionTicks + }; + _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayBufferingRequest request) + { + var currentSession = GetSession(_sessionContext); + var syncPlayRequest = new PlaybackRequest() + { + Type = request.BufferingDone ? PlaybackRequestType.BufferingDone : PlaybackRequestType.Buffering, + When = DateTime.Parse(request.When), + PositionTicks = request.PositionTicks + }; + _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + public void Post(SyncPlayUpdatePing request) + { + var currentSession = GetSession(_sessionContext); + var syncPlayRequest = new PlaybackRequest() + { + Type = PlaybackRequestType.UpdatePing, + Ping = Convert.ToInt64(request.Ping) + }; + _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); + } + } +} diff --git a/MediaBrowser.Api/SyncPlay/TimeSyncService.cs b/MediaBrowser.Api/SyncPlay/TimeSyncService.cs new file mode 100644 index 000000000..4a9307e62 --- /dev/null +++ b/MediaBrowser.Api/SyncPlay/TimeSyncService.cs @@ -0,0 +1,52 @@ +using System; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Services; +using MediaBrowser.Model.SyncPlay; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Api.SyncPlay +{ + [Route("/GetUtcTime", "GET", Summary = "Get UtcTime")] + public class GetUtcTime : IReturnVoid + { + // Nothing + } + + /// <summary> + /// Class TimeSyncService. + /// </summary> + public class TimeSyncService : BaseApiService + { + public TimeSyncService( + ILogger<TimeSyncService> logger, + IServerConfigurationManager serverConfigurationManager, + IHttpResultFactory httpResultFactory) + : base(logger, serverConfigurationManager, httpResultFactory) + { + // Do nothing + } + + /// <summary> + /// Handles the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <value>The current UTC time response.</value> + public UtcTimeResponse Get(GetUtcTime request) + { + // Important to keep the following line at the beginning + var requestReceptionTime = DateTime.UtcNow.ToUniversalTime().ToString("o"); + + var response = new UtcTimeResponse(); + response.RequestReceptionTime = requestReceptionTime; + + // Important to keep the following two lines at the end + var responseTransmissionTime = DateTime.UtcNow.ToUniversalTime().ToString("o"); + response.ResponseTransmissionTime = responseTransmissionTime; + + // Implementing NTP on such a high level results in this useless + // information being sent. On the other hand it enables future additions. + return response; + } + } +} diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs index f95fa7ca0..a6bacad4f 100644 --- a/MediaBrowser.Api/System/ActivityLogService.cs +++ b/MediaBrowser.Api/System/ActivityLogService.cs @@ -1,5 +1,7 @@ using System; using System.Globalization; +using System.Linq; +using Jellyfin.Data.Entities; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; @@ -53,7 +55,10 @@ namespace MediaBrowser.Api.System (DateTime?)null : DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime(); - var result = _activityManager.GetActivityLogEntries(minDate, request.HasUserId, request.StartIndex, request.Limit); + var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>( + entries => entries.Where(entry => entry.DateCreated >= minDate)); + + var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs index f8b6ee65d..8e4860be4 100644 --- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs +++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; using System.Threading.Tasks; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; @@ -10,7 +10,7 @@ namespace MediaBrowser.Api.System /// <summary> /// Class SessionInfoWebSocketListener /// </summary> - public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<List<ActivityLogEntry>, WebSocketListenerState> + public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState> { /// <summary> /// Gets the name. @@ -26,10 +26,10 @@ namespace MediaBrowser.Api.System public ActivityLogWebSocketListener(ILogger<ActivityLogWebSocketListener> logger, IActivityManager activityManager) : base(logger) { _activityManager = activityManager; - _activityManager.EntryCreated += _activityManager_EntryCreated; + _activityManager.EntryCreated += OnEntryCreated; } - void _activityManager_EntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e) + private void OnEntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e) { SendData(true); } @@ -38,15 +38,15 @@ namespace MediaBrowser.Api.System /// Gets the data to send. /// </summary> /// <returns>Task{SystemInfo}.</returns> - protected override Task<List<ActivityLogEntry>> GetDataToSend() + protected override Task<ActivityLogEntry[]> GetDataToSend() { - return Task.FromResult(new List<ActivityLogEntry>()); + return Task.FromResult(Array.Empty<ActivityLogEntry>()); } - + /// <inheritdoc /> protected override void Dispose(bool dispose) { - _activityManager.EntryCreated -= _activityManager_EntryCreated; + _activityManager.EntryCreated -= OnEntryCreated; base.Dispose(dispose); } diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index 3d08d5437..bef91d54d 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -51,7 +51,7 @@ namespace MediaBrowser.Api.UserLibrary public class ArtistsService : BaseItemsByNameService<MusicArtist> { public ArtistsService( - ILogger<GenresService> logger, + ILogger<ArtistsService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index c4a52d5f5..559082ff4 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="userDataRepository">The user data repository.</param> /// <param name="dtoService">The dto service.</param> protected BaseItemsByNameService( - ILogger logger, + ILogger<BaseItemsByNameService<TItemType>> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index c4d44042b..f3c0441e1 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="localization">The localization.</param> /// <param name="dtoService">The dto service.</param> public ItemsService( - ILogger logger, + ILogger<ItemsService> logger, IServerConfigurationManager serverConfigurationManager, IHttpResultFactory httpResultFactory, IUserManager userManager, diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index b11fd48d3..957a279f8 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -128,6 +128,7 @@ namespace MediaBrowser.Api var items = request.Ids.Split(',') .Select(i => _libraryManager.GetItemById(i)) .OfType<Video>() + .OrderBy(i => i.Id) .ToList(); if (items.Count < 2) |
