diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs index 4f84652c6..de7987bd2 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -29,7 +30,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// /// The _task queue /// - private readonly SortedDictionary _taskQueue = new SortedDictionary(); + private readonly ConcurrentQueue> _taskQueue = + new ConcurrentQueue>(); /// /// Gets or sets the json serializer. @@ -136,25 +138,17 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { var type = task.ScheduledTask.GetType(); + Logger.Info("Queueing task {0}", type.Name); + lock (_taskQueue) { - // If it's idle just execute immediately if (task.State == TaskState.Idle) { Execute(task, options); return; } - if (!_taskQueue.ContainsKey(type)) - { - Logger.Info("Queueing task {0}", type.Name); - _taskQueue.Add(type, options); - } - else - { - _taskQueue[type] = options; - Logger.Info("Task already queued: {0}", type.Name); - } + _taskQueue.Enqueue(new Tuple(type, options)); } } @@ -241,15 +235,24 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks // Execute queued tasks lock (_taskQueue) { - foreach (var enqueuedType in _taskQueue.ToList()) + var list = new List>(); + + Tuple item; + while (_taskQueue.TryDequeue(out item)) { - var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Key); + if (list.All(i => i.Item1 != item.Item1)) + { + list.Add(item); + } + } + + foreach (var enqueuedType in list) + { + var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1); if (scheduledTask.State == TaskState.Idle) { - Execute(scheduledTask, enqueuedType.Value); - - _taskQueue.Remove(enqueuedType.Key); + Execute(scheduledTask, enqueuedType.Item2); } } } diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index 7f83aa61d..6083c88de 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -186,18 +186,17 @@ namespace MediaBrowser.LocalMetadata.Images names.Add("movie"); } - foreach (var name in names) - { - AddImage(files, images, imagePrefix + name, ImageType.Primary); - } - var fileNameWithoutExtension = item.FileNameWithoutExtension; - if (!string.IsNullOrEmpty(fileNameWithoutExtension)) { AddImage(files, images, fileNameWithoutExtension, ImageType.Primary); } + foreach (var name in names) + { + AddImage(files, images, imagePrefix + name, ImageType.Primary); + } + if (!isInMixedFolder) { foreach (var name in names) diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs index 5474892e8..d78d5e8ea 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs @@ -233,57 +233,45 @@ namespace MediaBrowser.Server.Implementations.Drawing await semaphore.WaitAsync().ConfigureAwait(false); - // Check again in case of lock contention - try - { - if (File.Exists(cacheFilePath)) - { - semaphore.Release(); - return cacheFilePath; - } - } - catch - { - semaphore.Release(); - throw; - } - try { CheckDisposed(); - var newWidth = Convert.ToInt32(newSize.Width); - var newHeight = Convert.ToInt32(newSize.Height); - - Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - - if (string.IsNullOrWhiteSpace(options.BackgroundColor)) + if (!File.Exists(cacheFilePath)) { - using (var originalImage = new MagickWand(originalImagePath)) - { - originalImage.CurrentImage.ResizeImage(newWidth, newHeight); + var newWidth = Convert.ToInt32(newSize.Width); + var newHeight = Convert.ToInt32(newSize.Height); - DrawIndicator(originalImage, newWidth, newHeight, options); + Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - originalImage.CurrentImage.CompressionQuality = quality; - - originalImage.SaveImage(cacheFilePath); - } - } - else - { - using (var wand = new MagickWand(newWidth, newHeight, options.BackgroundColor)) + if (string.IsNullOrWhiteSpace(options.BackgroundColor)) { using (var originalImage = new MagickWand(originalImagePath)) { originalImage.CurrentImage.ResizeImage(newWidth, newHeight); - wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); - DrawIndicator(wand, newWidth, newHeight, options); + DrawIndicator(originalImage, newWidth, newHeight, options); - wand.CurrentImage.CompressionQuality = quality; + originalImage.CurrentImage.CompressionQuality = quality; - wand.SaveImage(cacheFilePath); + originalImage.SaveImage(cacheFilePath); + } + } + else + { + using (var wand = new MagickWand(newWidth, newHeight, options.BackgroundColor)) + { + using (var originalImage = new MagickWand(originalImagePath)) + { + originalImage.CurrentImage.ResizeImage(newWidth, newHeight); + + wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); + DrawIndicator(wand, newWidth, newHeight, options); + + wand.CurrentImage.CompressionQuality = quality; + + wand.SaveImage(cacheFilePath); + } } } } diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index 815756f9b..c5b4abf62 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.IO; +using System.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; @@ -9,7 +10,6 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Sync; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -152,7 +152,7 @@ namespace MediaBrowser.Server.Implementations.Sync try { - var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem, target, cancellationToken).ConfigureAwait(false); + var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath, target, cancellationToken).ConfigureAwait(false); if (localItem.Item.MediaSources != null) { @@ -173,10 +173,6 @@ namespace MediaBrowser.Server.Implementations.Sync var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); if (mediaSource != null) { - mediaSource.Path = sendFileResult.Path; - mediaSource.Protocol = sendFileResult.Protocol; - mediaSource.SupportsTranscoding = false; - await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, cancellationToken).ConfigureAwait(false); } } @@ -216,7 +212,8 @@ namespace MediaBrowser.Server.Implementations.Sync { try { - var sendFileResult = await SendFile(provider, mediaStream.Path, localItem, target, cancellationToken).ConfigureAwait(false); + var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target); + var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, cancellationToken).ConfigureAwait(false); mediaStream.Path = sendFileResult.Path; requiresSave = true; @@ -240,6 +237,38 @@ namespace MediaBrowser.Server.Implementations.Sync } } + private string GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target) + { + var path = item.LocalPath; + + var filename = GetSubtitleSaveFileName(item, stream.Language, stream.IsForced) + "." + stream.Codec.ToLower(); + + var parentPath = provider.GetParentDirectoryPath(path, target); + + path = Path.Combine(parentPath, filename); + + return path; + } + + private string GetSubtitleSaveFileName(LocalItem item, string language, bool isForced) + { + var path = item.LocalPath; + + var name = Path.GetFileNameWithoutExtension(path); + + if (!string.IsNullOrWhiteSpace(language)) + { + name += "." + language.ToLower(); + } + + if (isForced) + { + name += ".foreign"; + } + + return name; + } + private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, @@ -264,12 +293,12 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task SendFile(IServerSyncProvider provider, string inputPath, LocalItem item, SyncTarget target, CancellationToken cancellationToken) + private async Task SendFile(IServerSyncProvider provider, string inputPath, string remotePath, SyncTarget target, CancellationToken cancellationToken) { - _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, item.LocalPath); + _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, remotePath); using (var stream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) { - return await provider.SendFile(stream, item.LocalPath, target, new Progress(), cancellationToken).ConfigureAwait(false); + return await provider.SendFile(stream, remotePath, target, new Progress(), cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 22c59610b..b73e0e85f 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -632,7 +632,8 @@ namespace MediaBrowser.Server.Implementations.Sync IsExternal = true, Language = subtitle.Language, Path = fileInfo.Path, - SupportsExternalStream = true + SupportsExternalStream = true, + Type = MediaStreamType.Subtitle }); startingIndex++;