diff options
21 files changed, 311 insertions, 239 deletions
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index deaefe019..10bc53b74 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -564,25 +564,59 @@ namespace MediaBrowser.Api.Images cacheDuration = TimeSpan.FromDays(365); } - // Avoid implicitly captured closure - var currentItem = item; - var currentRequest = request; - var responseHeaders = new Dictionary<string, string> { {"transferMode.dlna.org", "Interactive"}, {"realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"} }; - return ToCachedResult(cacheGuid, originalFileImageDateModified, cacheDuration, () => new ImageWriter + return GetImageResult(item, + request, + imageInfo, + supportedImageEnhancers, + contentType, + cacheDuration, + responseHeaders) + .Result; + } + + private async Task<object> GetImageResult(IHasImages item, + ImageRequest request, + ItemImageInfo image, + List<IImageEnhancer> enhancers, + string contentType, + TimeSpan? cacheDuration, + IDictionary<string,string> headers) + { + var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art; + + if (request.CropWhitespace.HasValue) + { + cropwhitespace = request.CropWhitespace.Value; + } + + var options = new ImageProcessingOptions { - Item = currentItem, - Request = currentRequest, - Enhancers = supportedImageEnhancers, - Image = imageInfo, - ImageProcessor = _imageProcessor + CropWhiteSpace = cropwhitespace, + Enhancers = enhancers, + Height = request.Height, + ImageIndex = request.Index ?? 0, + Image = image, + Item = item, + MaxHeight = request.MaxHeight, + MaxWidth = request.MaxWidth, + Quality = request.Quality, + Width = request.Width, + OutputFormat = request.Format, + AddPlayedIndicator = request.AddPlayedIndicator, + PercentPlayed = request.PercentPlayed, + UnplayedCount = request.UnplayedCount, + BackgroundColor = request.BackgroundColor + }; - }, contentType, responseHeaders); + var file = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); + + return ResultFactory.GetStaticFileResult(Request, file, contentType, cacheDuration, FileShare.Read, headers); } private string GetMimeType(ImageOutputFormat format, string path) @@ -603,6 +637,10 @@ namespace MediaBrowser.Api.Images { return Common.Net.MimeTypes.GetMimeType("i.png"); } + if (format == ImageOutputFormat.Webp) + { + return Common.Net.MimeTypes.GetMimeType("i.webp"); + } return Common.Net.MimeTypes.GetMimeType(path); } diff --git a/MediaBrowser.Api/Images/ImageWriter.cs b/MediaBrowser.Api/Images/ImageWriter.cs deleted file mode 100644 index b6638d9df..000000000 --- a/MediaBrowser.Api/Images/ImageWriter.cs +++ /dev/null @@ -1,96 +0,0 @@ -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using ServiceStack.Web; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.Images -{ - /// <summary> - /// Class ImageWriter - /// </summary> - public class ImageWriter : IStreamWriter, IHasOptions - { - public List<IImageEnhancer> Enhancers; - - /// <summary> - /// Gets or sets the request. - /// </summary> - /// <value>The request.</value> - public ImageRequest Request { get; set; } - /// <summary> - /// Gets or sets the item. - /// </summary> - /// <value>The item.</value> - public IHasImages Item { get; set; } - /// <summary> - /// The original image date modified - /// </summary> - public ItemImageInfo Image; - - public IImageProcessor ImageProcessor { get; set; } - - /// <summary> - /// The _options - /// </summary> - private readonly IDictionary<string, string> _options = new Dictionary<string, string>(); - /// <summary> - /// Gets the options. - /// </summary> - /// <value>The options.</value> - public IDictionary<string, string> Options - { - get { return _options; } - } - - /// <summary> - /// Writes to. - /// </summary> - /// <param name="responseStream">The response stream.</param> - public void WriteTo(Stream responseStream) - { - var task = WriteToAsync(responseStream); - - Task.WaitAll(task); - } - - /// <summary> - /// Writes to async. - /// </summary> - /// <param name="responseStream">The response stream.</param> - /// <returns>Task.</returns> - private Task WriteToAsync(Stream responseStream) - { - var cropwhitespace = Request.Type == ImageType.Logo || Request.Type == ImageType.Art; - - if (Request.CropWhitespace.HasValue) - { - cropwhitespace = Request.CropWhitespace.Value; - } - - var options = new ImageProcessingOptions - { - CropWhiteSpace = cropwhitespace, - Enhancers = Enhancers, - Height = Request.Height, - ImageIndex = Request.Index ?? 0, - Image = Image, - Item = Item, - MaxHeight = Request.MaxHeight, - MaxWidth = Request.MaxWidth, - Quality = Request.Quality, - Width = Request.Width, - OutputFormat = Request.Format, - AddPlayedIndicator = Request.AddPlayedIndicator, - PercentPlayed = Request.PercentPlayed, - UnplayedCount = Request.UnplayedCount, - BackgroundColor = Request.BackgroundColor - }; - - return ImageProcessor.ProcessImage(options, responseStream); - } - } -} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 6a1e45e25..f3857ce30 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -85,7 +85,6 @@ <Compile Include="Images\ImageByNameService.cs" /> <Compile Include="Images\ImageRequest.cs" /> <Compile Include="Images\ImageService.cs" /> - <Compile Include="Images\ImageWriter.cs" /> <Compile Include="Music\InstantMixService.cs" /> <Compile Include="ItemLookupService.cs" /> <Compile Include="ItemRefreshService.cs" /> @@ -102,7 +101,6 @@ <Compile Include="PackageReviewService.cs" /> <Compile Include="PackageService.cs" /> <Compile Include="Playback\BifService.cs" /> - <Compile Include="Playback\EndlessStreamCopy.cs" /> <Compile Include="Playback\Hls\BaseHlsService.cs" /> <Compile Include="Playback\Hls\DynamicHlsService.cs" /> <Compile Include="Playback\Hls\HlsSegmentService.cs" /> @@ -123,6 +121,7 @@ <Compile Include="SearchService.cs" /> <Compile Include="SessionsService.cs" /> <Compile Include="SimilarItemsHelper.cs" /> + <Compile Include="Sync\SyncService.cs" /> <Compile Include="SystemService.cs" /> <Compile Include="Movies\TrailersService.cs" /> <Compile Include="TvShowsService.cs" /> diff --git a/MediaBrowser.Api/Playback/EndlessStreamCopy.cs b/MediaBrowser.Api/Playback/EndlessStreamCopy.cs deleted file mode 100644 index 40586261f..000000000 --- a/MediaBrowser.Api/Playback/EndlessStreamCopy.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.Playback -{ - public class EndlessStreamCopy - { - public async Task CopyStream(Stream source, Stream target, CancellationToken cancellationToken) - { - long position = 0; - - while (!cancellationToken.IsCancellationRequested) - { - await source.CopyToAsync(target, 81920, cancellationToken).ConfigureAwait(false); - - var fsPosition = source.Position; - - var bytesRead = fsPosition - position; - - //Logger.Debug("Streamed {0} bytes from file {1}", bytesRead, path); - - if (bytesRead == 0) - { - await Task.Delay(100, cancellationToken).ConfigureAwait(false); - } - - position = fsPosition; - } - } - } -} diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index dd8960649..80428269b 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -149,7 +149,7 @@ namespace MediaBrowser.Api.Playback.Progressive using (state) { - return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, FileShare.Read, responseHeaders, isHeadRequest); + return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, null, FileShare.Read, responseHeaders, isHeadRequest); } } @@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Playback.Progressive try { - return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, FileShare.Read, responseHeaders, isHeadRequest); + return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, null, FileShare.Read, responseHeaders, isHeadRequest); } finally { @@ -285,7 +285,8 @@ namespace MediaBrowser.Api.Playback.Progressive state.Dispose(); } - var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem); + var job = ApiEntryPoint.Instance.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); + var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem, job); result.Options["Content-Type"] = contentType; diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index 36ae7f100..a4c55443c 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -12,6 +12,7 @@ namespace MediaBrowser.Api.Playback.Progressive private string Path { get; set; } private ILogger Logger { get; set; } private readonly IFileSystem _fileSystem; + private readonly TranscodingJob _job; /// <summary> /// The _options @@ -32,11 +33,12 @@ namespace MediaBrowser.Api.Playback.Progressive /// <param name="path">The path.</param> /// <param name="logger">The logger.</param> /// <param name="fileSystem">The file system.</param> - public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem) + public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem, TranscodingJob job) { Path = path; Logger = logger; _fileSystem = fileSystem; + _job = job; } /// <summary> @@ -59,7 +61,8 @@ namespace MediaBrowser.Api.Playback.Progressive { try { - await new ProgressiveFileCopier(_fileSystem).StreamFile(Path, responseStream).ConfigureAwait(false); + await new ProgressiveFileCopier(_fileSystem, _job) + .StreamFile(Path, responseStream).ConfigureAwait(false); } catch { @@ -77,10 +80,12 @@ namespace MediaBrowser.Api.Playback.Progressive public class ProgressiveFileCopier { private readonly IFileSystem _fileSystem; + private readonly TranscodingJob _job; - public ProgressiveFileCopier(IFileSystem fileSystem) + public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job) { _fileSystem = fileSystem; + _job = job; } public async Task StreamFile(string path, Stream outputStream) @@ -102,7 +107,10 @@ namespace MediaBrowser.Api.Playback.Progressive if (bytesRead == 0) { - eofCount++; + if (_job == null || _job.HasExited) + { + eofCount++; + } await Task.Delay(100).ConfigureAwait(false); } else diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs new file mode 100644 index 000000000..73c04edaa --- /dev/null +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -0,0 +1,106 @@ +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Sync; +using ServiceStack; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Sync +{ + [Route("/Sync/Jobs/{Id}", "DELETE", Summary = "Cancels a sync job.")] + public class CancelSyncJob : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Sync/Schedules/{Id}", "DELETE", Summary = "Cancels a sync job.")] + public class CancelSyncSchedule : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Sync/Jobs/{Id}", "GET", Summary = "Gets a sync job.")] + public class GetSyncJob : IReturn<SyncJob> + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Sync/Schedules/{Id}", "GET", Summary = "Gets a sync job.")] + public class GetSyncSchedule : IReturn<SyncSchedule> + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Sync/Jobs", "GET", Summary = "Gets sync jobs.")] + public class GetSyncJobs : IReturn<QueryResult<SyncJob>> + { + } + + [Route("/Sync/Schedules", "GET", Summary = "Gets sync schedules.")] + public class GetSyncSchedules : IReturn<QueryResult<SyncSchedule>> + { + } + + [Authenticated] + public class SyncService : BaseApiService + { + private readonly ISyncManager _syncManager; + + public SyncService(ISyncManager syncManager) + { + _syncManager = syncManager; + } + + public object Get(GetSyncJobs request) + { + var result = _syncManager.GetJobs(new SyncJobQuery + { + + }); + + return ToOptimizedResult(result); + } + + public object Get(GetSyncSchedules request) + { + var result = _syncManager.GetSchedules(new SyncScheduleQuery + { + + }); + + return ToOptimizedResult(result); + } + + public object Get(GetSyncJob request) + { + var result = _syncManager.GetJob(request.Id); + + return ToOptimizedResult(result); + } + + public object Get(GetSyncSchedule request) + { + var result = _syncManager.GetSchedule(request.Id); + + return ToOptimizedResult(result); + } + + public void Delete(CancelSyncJob request) + { + var task = _syncManager.CancelJob(request.Id); + + Task.WaitAll(task); + } + + public void Delete(CancelSyncSchedule request) + { + var task = _syncManager.CancelSchedule(request.Id); + + Task.WaitAll(task); + } + } +} diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Common/Net/MimeTypes.cs index dcac5e7ba..0740bf6d1 100644 --- a/MediaBrowser.Common/Net/MimeTypes.cs +++ b/MediaBrowser.Common/Net/MimeTypes.cs @@ -143,6 +143,10 @@ namespace MediaBrowser.Common.Net { return "image/png"; } + if (ext.Equals(".webp", StringComparison.OrdinalIgnoreCase)) + { + return "image/webp"; + } if (ext.Equals(".ico", StringComparison.OrdinalIgnoreCase)) { return "image/vnd.microsoft.icon"; diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 51466c4f9..a0128f111 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -73,6 +73,13 @@ namespace MediaBrowser.Controller.Drawing /// <param name="toStream">To stream.</param> /// <returns>Task.</returns> Task ProcessImage(ImageProcessingOptions options, Stream toStream); + + /// <summary> + /// Processes the image. + /// </summary> + /// <param name="options">The options.</param> + /// <returns>Task.</returns> + Task<string> ProcessImage(ImageProcessingOptions options); /// <summary> /// Gets the enhanced image. diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index f7984c32c..665c1f8d9 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -80,9 +80,13 @@ namespace MediaBrowser.Controller.Net /// <param name="responseHeaders">The response headers.</param> /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> /// <returns>System.Object.</returns> - object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, - TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn, - IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false); + object GetStaticResult(IRequest requestContext, + Guid cacheKey, + DateTime? lastDateModified, + TimeSpan? cacheDuration, + string contentType, Func<Task<Stream>> factoryFn, + IDictionary<string, string> responseHeaders = null, + bool isHeadRequest = false); /// <summary> /// Gets the static file result. @@ -101,11 +105,18 @@ namespace MediaBrowser.Controller.Net /// <param name="requestContext">The request context.</param> /// <param name="path">The path.</param> /// <param name="contentType">Type of the content.</param> + /// <param name="cacheCuration">The cache curation.</param> /// <param name="fileShare">The file share.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> /// <returns>System.Object.</returns> - object GetStaticFileResult(IRequest requestContext, string path, string contentType, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false); + object GetStaticFileResult(IRequest requestContext, + string path, + string contentType, + TimeSpan? cacheCuration = null, + FileShare fileShare = FileShare.Read, + IDictionary<string, string> responseHeaders = null, + bool isHeadRequest = false); /// <summary> /// Gets the optimized serialized result using cache. diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index fc92718ca..63a5d8a7c 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -34,6 +34,20 @@ namespace MediaBrowser.Controller.Sync QueryResult<SyncSchedule> GetSchedules(SyncScheduleQuery query); /// <summary> + /// Gets the job. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>SyncJob.</returns> + SyncJob GetJob(string id); + + /// <summary> + /// Gets the schedule. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>SyncSchedule.</returns> + SyncSchedule GetSchedule(string id); + + /// <summary> /// Cancels the job. /// </summary> /// <param name="id">The identifier.</param> diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index 048a7a0cf..333521bb5 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Dlna _logger = logger; _jsonSerializer = jsonSerializer; - DumpProfiles(); + //DumpProfiles(); } public IEnumerable<DeviceProfile> GetProfiles() diff --git a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs index b9c4b25bc..d12b3598c 100644 --- a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs +++ b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Dlna.Profiles { @@ -198,7 +197,7 @@ namespace MediaBrowser.Dlna.Profiles { new SubtitleProfile { - Format = SubtitleFormat.SRT + Format = "srt" } }; } diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs index 4611edc18..b90c906fb 100644 --- a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs @@ -343,7 +343,7 @@ namespace MediaBrowser.Dlna.Profiles { new SubtitleProfile { - Format = SubtitleFormat.SMI + Format = "smi" } }; } diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs index 86bd6b731..09071cbf9 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs @@ -118,14 +118,19 @@ namespace MediaBrowser.Server.Implementations.Drawing public async Task ProcessImage(ImageProcessingOptions options, Stream toStream) { - if (options == null) + var file = await ProcessImage(options).ConfigureAwait(false); + + using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true)) { - throw new ArgumentNullException("options"); + await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } + } - if (toStream == null) + public async Task<string> ProcessImage(ImageProcessingOptions options) + { + if (options == null) { - throw new ArgumentNullException("toStream"); + throw new ArgumentNullException("options"); } var originalImagePath = options.Image.Path; @@ -133,11 +138,7 @@ namespace MediaBrowser.Server.Implementations.Drawing if (options.HasDefaultOptions() && options.Enhancers.Count == 0 && !options.CropWhiteSpace) { // Just spit out the original file if all the options are default - using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) - { - await fileStream.CopyToAsync(toStream).ConfigureAwait(false); - return; - } + return originalImagePath; } var dateModified = options.Image.DateModified; @@ -166,30 +167,13 @@ namespace MediaBrowser.Server.Implementations.Drawing if (options.HasDefaultOptionsWithoutSize() && newSize.Equals(originalImageSize) && options.Enhancers.Count == 0) { // Just spit out the original file if the new size equals the old - using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) - { - await fileStream.CopyToAsync(toStream).ConfigureAwait(false); - return; - } + return originalImagePath; } var quality = options.Quality ?? 90; var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, options.OutputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); - try - { - using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) - { - await fileStream.CopyToAsync(toStream).ConfigureAwait(false); - return; - } - } - catch (IOException) - { - // Cache file doesn't exist or is currently being written to - } - var semaphore = GetLock(cacheFilePath); await semaphore.WaitAsync().ConfigureAwait(false); @@ -197,17 +181,12 @@ namespace MediaBrowser.Server.Implementations.Drawing // Check again in case of lock contention try { - using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) + if (File.Exists(cacheFilePath)) { - await fileStream.CopyToAsync(toStream).ConfigureAwait(false); semaphore.Release(); - return; + return cacheFilePath; } } - catch (IOException) - { - // Cache file doesn't exist or is currently being written to - } catch { semaphore.Release(); @@ -218,37 +197,6 @@ namespace MediaBrowser.Server.Implementations.Drawing { var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed.HasValue; - //if (!hasPostProcessing) - //{ - // using (var outputStream = await _mediaEncoder.EncodeImage(new ImageEncodingOptions - // { - // InputPath = originalImagePath, - // MaxHeight = options.MaxHeight, - // MaxWidth = options.MaxWidth, - // Height = options.Height, - // Width = options.Width, - // Quality = options.Quality, - // Format = options.OutputFormat == ImageOutputFormat.Original ? Path.GetExtension(originalImagePath).TrimStart('.') : options.OutputFormat.ToString().ToLower() - - // }, CancellationToken.None).ConfigureAwait(false)) - // { - // using (var outputMemoryStream = new MemoryStream()) - // { - // // Save to the memory stream - // await outputStream.CopyToAsync(outputMemoryStream).ConfigureAwait(false); - - // var bytes = outputMemoryStream.ToArray(); - - // await toStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - - // // kick off a task to cache the result - // await CacheResizedImage(cacheFilePath, bytes).ConfigureAwait(false); - // } - - // return; - // } - //} - using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) { // Copy to memory stream to avoid Image locking file @@ -289,18 +237,16 @@ namespace MediaBrowser.Server.Implementations.Drawing var outputFormat = GetOutputFormat(originalImage, options.OutputFormat); - using (var outputMemoryStream = new MemoryStream()) + Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + + // Save to the cache location + using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, false)) { // Save to the memory stream - thumbnail.Save(outputFormat, outputMemoryStream, quality); - - var bytes = outputMemoryStream.ToArray(); - - await toStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - - // kick off a task to cache the result - await CacheResizedImage(cacheFilePath, bytes).ConfigureAwait(false); + thumbnail.Save(outputFormat, cacheFileStream, quality); } + + return cacheFilePath; } } @@ -324,9 +270,7 @@ namespace MediaBrowser.Server.Implementations.Drawing { try { - var parentPath = Path.GetDirectoryName(cacheFilePath); - - Directory.CreateDirectory(parentPath); + Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); // Save to the cache location using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index 8831d635c..6a60e5ea6 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -306,11 +306,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw new ArgumentNullException("path"); } - return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), fileShare, responseHeaders, isHeadRequest); + return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), null, fileShare, responseHeaders, isHeadRequest); } - public object GetStaticFileResult(IRequest requestContext, string path, string contentType, - FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, + public object GetStaticFileResult(IRequest requestContext, + string path, + string contentType, + TimeSpan? cacheCuration = null, + FileShare fileShare = FileShare.Read, + IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false) { if (string.IsNullOrEmpty(path)) @@ -327,7 +331,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer var cacheKey = path + dateModified.Ticks; - return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest); + return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, cacheCuration, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest); } /// <summary> diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index d88e2d6ab..187bcb59f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -319,5 +319,6 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications" } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index e203a6d9d..741bc52ca 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -882,5 +882,12 @@ "LabelAppName": "App name", "LabelAppNameExample": "Example: Sickbeard, NzbDrone", "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", - "ButtonEnterSupporterKey": "Enter supporter key" + "ButtonEnterSupporterKey": "Enter supporter key", + "HeaderHttpHeaders": "Http Headers", + "HeaderIdentificationHeader": "Identification Header", + "LabelValue": "Value:", + "LabelMatchType": "Match type:", + "OptionEquals": "Equals", + "OptionRegex": "Regex", + "OptionSubstring": "Substring" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 376a95e04..1bb789484 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -261,6 +261,7 @@ <Compile Include="Persistence\SqliteUserRepository.cs" /> <Compile Include="Sorting\StudioComparer.cs" /> <Compile Include="Sorting\VideoBitRateComparer.cs" /> + <Compile Include="Sync\SyncManager.cs" /> <Compile Include="Themes\AppThemeManager.cs" /> <Compile Include="Udp\UdpMessageReceivedEventArgs.cs" /> <Compile Include="Udp\UdpServer.cs" /> diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs new file mode 100644 index 000000000..373b30a41 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -0,0 +1,52 @@ +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class SyncManager : ISyncManager + { + public Task<List<SyncJob>> CreateJob(SyncJobRequest request) + { + throw new NotImplementedException(); + } + + public Task<SyncSchedule> CreateSchedule(SyncScheduleRequest request) + { + throw new NotImplementedException(); + } + + public QueryResult<SyncJob> GetJobs(SyncJobQuery query) + { + throw new NotImplementedException(); + } + + public QueryResult<SyncSchedule> GetSchedules(SyncScheduleQuery query) + { + throw new NotImplementedException(); + } + + public Task CancelJob(string id) + { + throw new NotImplementedException(); + } + + public Task CancelSchedule(string id) + { + throw new NotImplementedException(); + } + + public SyncJob GetJob(string id) + { + throw new NotImplementedException(); + } + + public SyncSchedule GetSchedule(string id) + { + throw new NotImplementedException(); + } + } +} diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 1e248ab57..60d1c92b4 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -33,6 +33,7 @@ using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Controller.Sync; using MediaBrowser.Controller.Themes; using MediaBrowser.Dlna; using MediaBrowser.Dlna.ConnectionManager; @@ -69,6 +70,7 @@ using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Implementations.Security; using MediaBrowser.Server.Implementations.ServerManager; using MediaBrowser.Server.Implementations.Session; +using MediaBrowser.Server.Implementations.Sync; using MediaBrowser.Server.Implementations.Themes; using MediaBrowser.Server.Implementations.WebSocket; using MediaBrowser.ServerApplication.EntryPoints; @@ -629,6 +631,8 @@ namespace MediaBrowser.ServerApplication MediaEncoder, ChapterManager); RegisterSingleInstance(EncodingManager); + RegisterSingleInstance<ISyncManager>(new SyncManager()); + var authContext = new AuthorizationContext(); RegisterSingleInstance<IAuthorizationContext>(authContext); RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager)); |
