diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 9faa8fceda..bcba9230ff 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -1440,5 +1440,12 @@ namespace MediaBrowser.Model.ApiClient /// The request. /// Task<SyncDataResponse>. Task SyncData(SyncDataRequest request); + + /// + /// Gets the synchronize job item file URL. + /// + /// The identifier. + /// System.String. + string GetSyncJobItemFileUrl(string id); } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 6175587a72..c5c6880e15 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -233,7 +233,8 @@ namespace MediaBrowser.Providers.Manager using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) { - await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken) + .ConfigureAwait(false); } if (_config.Configuration.SaveMetadataHidden) @@ -244,6 +245,11 @@ namespace MediaBrowser.Providers.Manager file.Attributes |= FileAttributes.Hidden; } } + catch (UnauthorizedAccessException ex) + { + _logger.Error("Error saving image to {0}", ex, path); + throw new Exception(string.Format("Error saving image to {0}", path), ex); + } finally { _libraryMonitor.ReportFileSystemChangeComplete(path, false); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index cceccceacf..6a999a7f4a 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -909,14 +909,6 @@ namespace MediaBrowser.Server.Implementations.Library return obj as T; } - /// - /// Creates an IBN item based on a given path - /// - /// - /// The path. - /// The name. - /// Task{``0}. - /// Path not created: + path private T CreateItemByName(string path, string name, Guid id) where T : BaseItem, new() { @@ -942,7 +934,15 @@ namespace MediaBrowser.Server.Implementations.Library if (!fileInfo.Exists) { - fileInfo = Directory.CreateDirectory(path); + try + { + fileInfo = Directory.CreateDirectory(path); + } + catch (UnauthorizedAccessException ex) + { + _logger.Error("Error creating directory {0}", ex, path); + throw new Exception(string.Format("Error creating directory {0}", path), ex); + } isNew = true; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 698806d09d..7fa5638896 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -326,13 +326,17 @@ namespace MediaBrowser.Server.Implementations.Sync Statuses = new List { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting } }); - var jobItems = result.Items; + await SyncJobItems(result.Items, true, progress, cancellationToken).ConfigureAwait(false); + } + + public async Task SyncJobItems(SyncJobItem[] items, bool enableConversion, IProgress progress, CancellationToken cancellationToken) + { var index = 0; - foreach (var item in jobItems) + foreach (var item in items) { double percent = index; - percent /= result.TotalRecordCount; + percent /= items.Length; progress.Report(100 * percent); @@ -341,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Sync var innerProgress = new ActionableProgress(); var job = _syncRepo.GetJob(item.JobId); - await ProcessJobItem(job, item, innerProgress, cancellationToken).ConfigureAwait(false); + await ProcessJobItem(job, item, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); job = _syncRepo.GetJob(item.JobId); await UpdateJobStatus(job).ConfigureAwait(false); @@ -350,7 +354,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, IProgress progress, CancellationToken cancellationToken) + private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { var item = _libraryManager.GetItemById(jobItem.ItemId); if (item == null) @@ -378,12 +382,12 @@ namespace MediaBrowser.Server.Implementations.Sync var video = item as Video; if (video != null) { - await Sync(jobItem, video, user, deviceProfile, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, video, user, deviceProfile, enableConversion, progress, cancellationToken).ConfigureAwait(false); } else if (item is Audio) { - await Sync(jobItem, (Audio)item, user, deviceProfile, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, (Audio)item, user, deviceProfile, enableConversion, progress, cancellationToken).ConfigureAwait(false); } else if (item is Photo) @@ -397,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task Sync(SyncJobItem jobItem, Video item, User user, DeviceProfile profile, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Video item, User user, DeviceProfile profile, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { var options = new VideoOptions { @@ -415,6 +419,11 @@ namespace MediaBrowser.Server.Implementations.Sync if (streamInfo.PlayMethod == PlayMethod.Transcode) { + if (!enableConversion) + { + return; + } + jobItem.Status = SyncJobItemStatus.Converting; jobItem.RequiresConversion = true; await _syncRepo.Update(jobItem).ConfigureAwait(false); @@ -463,7 +472,7 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); } - private async Task Sync(SyncJobItem jobItem, Audio item, User user, DeviceProfile profile, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Audio item, User user, DeviceProfile profile, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { var options = new AudioOptions { @@ -481,6 +490,11 @@ namespace MediaBrowser.Server.Implementations.Sync if (streamInfo.PlayMethod == PlayMethod.Transcode) { + if (!enableConversion) + { + return; + } + jobItem.Status = SyncJobItemStatus.Converting; jobItem.RequiresConversion = true; await _syncRepo.Update(jobItem).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 33db54ee1b..6843fb6047 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Sync @@ -126,6 +127,16 @@ namespace MediaBrowser.Server.Implementations.Sync await _repo.Create(job).ConfigureAwait(false); await processor.EnsureJobItems(job).ConfigureAwait(false); + + // If it already has a converting status then is must have been aborted during conversion + var jobItemsResult = _repo.GetJobItems(new SyncJobItemQuery + { + Statuses = new List { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, + JobId = jobId + }); + + await processor.SyncJobItems(jobItemsResult.Items, false, new Progress(), CancellationToken.None) + .ConfigureAwait(false); return new SyncJobCreationResult { diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index d7d4a2120d..b2e8ce2072 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.540 + 3.0.541 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index c8f2f24cb9..06fbc750fb 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.540 + 3.0.541 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index c793138500..c11f886c15 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.540 + 3.0.541 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 807e49e7f8..d183c9931a 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.540 + 3.0.541 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +