aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs4
-rw-r--r--MediaBrowser.Api/BaseApiService.cs4
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs64
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs15
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs22
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs16
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs14
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs15
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs2
-rw-r--r--MediaBrowser.Api/Movies/TrailersService.cs12
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs12
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs28
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs18
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/AudioService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs2
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs2
-rw-r--r--MediaBrowser.Api/Playback/UniversalAudioService.cs9
-rw-r--r--MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs57
-rw-r--r--MediaBrowser.Api/SyncPlay/SyncPlayService.cs302
-rw-r--r--MediaBrowser.Api/SyncPlay/TimeSyncService.cs52
-rw-r--r--MediaBrowser.Api/System/ActivityLogService.cs7
-rw-r--r--MediaBrowser.Api/System/ActivityLogWebSocketListener.cs16
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs2
-rw-r--r--MediaBrowser.Api/VideosService.cs1
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)