aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Sync
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/Sync')
-rw-r--r--MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs20
-rw-r--r--MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs33
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs190
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs321
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncRepository.cs107
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs12
7 files changed, 526 insertions, 165 deletions
diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
index 94eed50f6..6cc5be955 100644
--- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
@@ -8,7 +8,7 @@ using System.Linq;
namespace MediaBrowser.Server.Implementations.Sync
{
- public class AppSyncProvider : ISyncProvider
+ public class AppSyncProvider : ISyncProvider, IHasUniqueTargetIds
{
private readonly IDeviceManager _deviceManager;
@@ -30,9 +30,25 @@ namespace MediaBrowser.Server.Implementations.Sync
});
}
+ public IEnumerable<SyncTarget> GetSyncTargets(string userId)
+ {
+ return _deviceManager.GetDevices(new DeviceQuery
+ {
+ SupportsSync = true,
+ UserId = userId
+
+ }).Items.Select(i => new SyncTarget
+ {
+ Id = i.Id,
+ Name = i.Name
+ });
+ }
+
public DeviceProfile GetDeviceProfile(SyncTarget target)
{
- return new DeviceProfile();
+ var caps = _deviceManager.GetCapabilities(target.Id);
+
+ return caps == null || caps.DeviceProfile == null ? new DeviceProfile() : caps.DeviceProfile;
}
public string Name
diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
index fd12b1f8a..da3ecdfa6 100644
--- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Sync;
-using System;
using System.Collections.Generic;
using System.Linq;
@@ -10,7 +9,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{
public class CloudSyncProvider : ISyncProvider
{
- private ICloudSyncProvider[] _providers = new ICloudSyncProvider[] {};
+ private ICloudSyncProvider[] _providers = {};
public CloudSyncProvider(IApplicationHost appHost)
{
@@ -22,6 +21,11 @@ namespace MediaBrowser.Server.Implementations.Sync
return new List<SyncTarget>();
}
+ public IEnumerable<SyncTarget> GetSyncTargets(string userId)
+ {
+ return new List<SyncTarget>();
+ }
+
public DeviceProfile GetDeviceProfile(SyncTarget target)
{
return new DeviceProfile();
diff --git a/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs
deleted file mode 100644
index 7d29446b9..000000000
--- a/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Sync;
-using MediaBrowser.Model.Dlna;
-using MediaBrowser.Model.Sync;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Server.Implementations.Sync
-{
- public class MockSyncProvider : ISyncProvider
- {
- public string Name
- {
- get { return "Test Sync"; }
- }
-
- public IEnumerable<SyncTarget> GetSyncTargets()
- {
- return new List<SyncTarget>
- {
- new SyncTarget
- {
- Id = GetType().Name.GetMD5().ToString("N"),
- Name = Name
- }
- };
- }
-
- public DeviceProfile GetDeviceProfile(SyncTarget target)
- {
- return new DeviceProfile();
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 6dda869ee..896e49cb2 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -1,11 +1,15 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Sync;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.Sync;
using MoreLinq;
@@ -24,19 +28,18 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly ISyncManager _syncManager;
private readonly ILogger _logger;
private readonly IUserManager _userManager;
+ private readonly ITVSeriesManager _tvSeriesManager;
+ private readonly IMediaEncoder MediaEncoder;
- public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager)
+ public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder)
{
_libraryManager = libraryManager;
_syncRepo = syncRepo;
_syncManager = syncManager;
_logger = logger;
_userManager = userManager;
- }
-
- public void ProcessJobItem(SyncJob job, SyncJobItem jobItem, SyncTarget target)
- {
-
+ _tvSeriesManager = tvSeriesManager;
+ MediaEncoder = mediaEncoder;
}
public async Task EnsureJobItems(SyncJob job)
@@ -48,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.Sync
throw new InvalidOperationException("Cannot proceed with sync because user no longer exists.");
}
- var items = GetItemsForSync(job.RequestedItemIds, user, job.UnwatchedOnly)
+ var items = (await GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
.ToList();
var jobItems = _syncRepo.GetJobItems(new SyncJobItemQuery
@@ -62,7 +65,7 @@ namespace MediaBrowser.Server.Implementations.Sync
// Respect ItemLimit, if set
if (job.ItemLimit.HasValue)
{
- if (jobItems.Count >= job.ItemLimit.Value)
+ if (jobItems.Count(j => j.Status != SyncJobItemStatus.RemovedFromDevice && j.Status != SyncJobItemStatus.Failed) >= job.ItemLimit.Value)
{
break;
}
@@ -81,6 +84,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{
Id = Guid.NewGuid().ToString("N"),
ItemId = itemId,
+ ItemName = GetSyncJobItemName(item),
JobId = job.Id,
TargetId = job.TargetId,
DateCreated = DateTime.UtcNow
@@ -98,6 +102,11 @@ namespace MediaBrowser.Server.Implementations.Sync
await UpdateJobStatus(job, jobItems).ConfigureAwait(false);
}
+ private string GetSyncJobItemName(BaseItem item)
+ {
+ return item.Name;
+ }
+
public Task UpdateJobStatus(string id)
{
var job = _syncRepo.GetJob(id);
@@ -128,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Sync
foreach (var item in jobItems)
{
- if (item.Status == SyncJobItemStatus.Failed || item.Status == SyncJobItemStatus.Completed)
+ if (item.Status == SyncJobItemStatus.Failed || item.Status == SyncJobItemStatus.Synced || item.Status == SyncJobItemStatus.RemovedFromDevice)
{
pct += 100;
}
@@ -171,10 +180,11 @@ namespace MediaBrowser.Server.Implementations.Sync
return _syncRepo.Update(job);
}
- public IEnumerable<BaseItem> GetItemsForSync(IEnumerable<string> itemIds, User user, bool unwatchedOnly)
+ public async Task<IEnumerable<BaseItem>> GetItemsForSync(SyncCategory? category, string parentId, IEnumerable<string> itemIds, User user, bool unwatchedOnly)
{
- var items = itemIds
- .SelectMany(i => GetItemsForSync(i, user))
+ var items = category.HasValue ?
+ await GetItemsForSync(category.Value, parentId, user).ConfigureAwait(false) :
+ itemIds.SelectMany(i => GetItemsForSync(i, user))
.Where(_syncManager.SupportsSync);
if (unwatchedOnly)
@@ -198,6 +208,54 @@ namespace MediaBrowser.Server.Implementations.Sync
return items.DistinctBy(i => i.Id);
}
+ private async Task<IEnumerable<BaseItem>> GetItemsForSync(SyncCategory category, string parentId, User user)
+ {
+ var parent = string.IsNullOrWhiteSpace(parentId)
+ ? user.RootFolder
+ : (Folder)_libraryManager.GetItemById(parentId);
+
+ InternalItemsQuery query;
+
+ switch (category)
+ {
+ case SyncCategory.Latest:
+ query = new InternalItemsQuery
+ {
+ IsFolder = false,
+ SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName },
+ SortOrder = SortOrder.Descending,
+ Recursive = true
+ };
+ break;
+ case SyncCategory.Resume:
+ query = new InternalItemsQuery
+ {
+ IsFolder = false,
+ SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName },
+ SortOrder = SortOrder.Descending,
+ Recursive = true,
+ IsResumable = true,
+ MediaTypes = new[] { MediaType.Video }
+ };
+ break;
+
+ case SyncCategory.NextUp:
+ return _tvSeriesManager.GetNextUp(new NextUpQuery
+ {
+ ParentId = parentId,
+ UserId = user.Id.ToString("N")
+ }).Items;
+
+ default:
+ throw new ArgumentException("Unrecognized category: " + category);
+ }
+
+ query.User = user;
+
+ var result = await parent.GetItems(query).ConfigureAwait(false);
+ return result.Items;
+ }
+
private IEnumerable<BaseItem> GetItemsForSync(string id, User user)
{
var item = _libraryManager.GetItemById(id);
@@ -261,9 +319,10 @@ namespace MediaBrowser.Server.Implementations.Sync
{
await EnsureSyncJobs(cancellationToken).ConfigureAwait(false);
+ // If it already has a converting status then is must have been aborted during conversion
var result = _syncRepo.GetJobItems(new SyncJobItemQuery
{
- IsCompleted = false
+ Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }
});
var jobItems = result.Items;
@@ -278,10 +337,7 @@ namespace MediaBrowser.Server.Implementations.Sync
cancellationToken.ThrowIfCancellationRequested();
- if (item.Status == SyncJobItemStatus.Queued)
- {
- await ProcessJobItem(item, cancellationToken).ConfigureAwait(false);
- }
+ await ProcessJobItem(item, cancellationToken).ConfigureAwait(false);
var job = _syncRepo.GetJob(item.JobId);
await UpdateJobStatus(job).ConfigureAwait(false);
@@ -316,39 +372,30 @@ namespace MediaBrowser.Server.Implementations.Sync
var video = item as Video;
if (video != null)
{
- jobItem.OutputPath = await Sync(jobItem, video, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, video, deviceProfile, cancellationToken).ConfigureAwait(false);
}
else if (item is Audio)
{
- jobItem.OutputPath = await Sync(jobItem, (Audio)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, (Audio)item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
else if (item is Photo)
{
- jobItem.OutputPath = await Sync(jobItem, (Photo)item, deviceProfile, cancellationToken).ConfigureAwait(false);
- }
-
- else if (item is Game)
- {
- jobItem.OutputPath = await Sync(jobItem, (Game)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, (Photo)item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
- else if (item is Book)
+ else
{
- jobItem.OutputPath = await Sync(jobItem, (Book)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await SyncGeneric(jobItem, item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
-
- jobItem.Progress = 50;
- jobItem.Status = SyncJobItemStatus.Transferring;
- await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken)
{
var options = new VideoOptions
{
- Context = EncodingContext.Streaming,
+ Context = EncodingContext.Static,
ItemId = item.Id.ToString("N"),
DeviceId = jobItem.TargetId,
Profile = profile,
@@ -358,28 +405,41 @@ namespace MediaBrowser.Server.Implementations.Sync
var streamInfo = new StreamBuilder().BuildVideoItem(options);
var mediaSource = streamInfo.MediaSource;
- if (streamInfo.PlayMethod != PlayMethod.Transcode)
+ jobItem.MediaSourceId = streamInfo.MediaSourceId;
+
+ if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ {
+ jobItem.Status = SyncJobItemStatus.Converting;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
+
+ jobItem.OutputPath = await MediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile), new Progress<double>(), cancellationToken);
+ }
+ else
{
if (mediaSource.Protocol == MediaProtocol.File)
{
- return mediaSource.Path;
+ jobItem.OutputPath = mediaSource.Path;
}
- if (mediaSource.Protocol == MediaProtocol.Http)
+ else if (mediaSource.Protocol == MediaProtocol.Http)
{
- return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
- throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
- // TODO: Transcode
- return mediaSource.Path;
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
{
var options = new AudioOptions
{
- Context = EncodingContext.Streaming,
+ Context = EncodingContext.Static,
ItemId = item.Id.ToString("N"),
DeviceId = jobItem.TargetId,
Profile = profile,
@@ -389,36 +449,52 @@ namespace MediaBrowser.Server.Implementations.Sync
var streamInfo = new StreamBuilder().BuildAudioItem(options);
var mediaSource = streamInfo.MediaSource;
- if (streamInfo.PlayMethod != PlayMethod.Transcode)
+ jobItem.MediaSourceId = streamInfo.MediaSourceId;
+
+ if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ {
+ jobItem.Status = SyncJobItemStatus.Converting;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
+
+ jobItem.OutputPath = await MediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile), new Progress<double>(), cancellationToken);
+ }
+ else
{
if (mediaSource.Protocol == MediaProtocol.File)
{
- return mediaSource.Path;
+ jobItem.OutputPath = mediaSource.Path;
}
- if (mediaSource.Protocol == MediaProtocol.Http)
+ else if (mediaSource.Protocol == MediaProtocol.Http)
{
- return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
- throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
- // TODO: Transcode
- return mediaSource.Path;
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Photo item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Photo item, DeviceProfile profile, CancellationToken cancellationToken)
{
- return item.Path;
- }
+ jobItem.OutputPath = item.Path;
- private async Task<string> Sync(SyncJobItem jobItem, Game item, DeviceProfile profile, CancellationToken cancellationToken)
- {
- return item.Path;
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Book item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task SyncGeneric(SyncJobItem jobItem, BaseItem item, DeviceProfile profile, CancellationToken cancellationToken)
{
- return item.Path;
+ jobItem.OutputPath = item.Path;
+
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
private async Task<string> DownloadFile(SyncJobItem jobItem, MediaSourceInfo mediaSource, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index 664ec4038..3b2d70f84 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -1,18 +1,27 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Sync;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
+using MediaBrowser.Model.Users;
using MoreLinq;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -25,16 +34,24 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IImageProcessor _imageProcessor;
private readonly ILogger _logger;
private readonly IUserManager _userManager;
+ private readonly Func<IDtoService> _dtoService;
+ private readonly IApplicationHost _appHost;
+ private readonly ITVSeriesManager _tvSeriesManager;
+ private readonly Func<IMediaEncoder> _mediaEncoder;
private ISyncProvider[] _providers = { };
- public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager)
+ public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder)
{
_libraryManager = libraryManager;
_repo = repo;
_imageProcessor = imageProcessor;
_logger = logger;
_userManager = userManager;
+ _dtoService = dtoService;
+ _appHost = appHost;
+ _tvSeriesManager = tvSeriesManager;
+ _mediaEncoder = mediaEncoder;
}
public void AddParts(IEnumerable<ISyncProvider> providers)
@@ -44,12 +61,12 @@ namespace MediaBrowser.Server.Implementations.Sync
public async Task<SyncJobCreationResult> CreateJob(SyncJobRequest request)
{
- var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager);
+ var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder());
var user = _userManager.GetUserById(request.UserId);
- var items = processor
- .GetItemsForSync(request.ItemIds, user, request.UnwatchedOnly)
+ var items = (await processor
+ .GetItemsForSync(request.Category, request.ParentId, request.ItemIds, user, request.UnwatchedOnly).ConfigureAwait(false))
.ToList();
if (items.Any(i => !SupportsSync(i)))
@@ -57,9 +74,12 @@ namespace MediaBrowser.Server.Implementations.Sync
throw new ArgumentException("Item does not support sync.");
}
- if (string.IsNullOrWhiteSpace(request.Name) && request.ItemIds.Count == 1)
+ if (string.IsNullOrWhiteSpace(request.Name))
{
- request.Name = GetDefaultName(_libraryManager.GetItemById(request.ItemIds[0]));
+ if (request.ItemIds.Count == 1)
+ {
+ request.Name = GetDefaultName(_libraryManager.GetItemById(request.ItemIds[0]));
+ }
}
if (string.IsNullOrWhiteSpace(request.Name))
@@ -68,7 +88,12 @@ namespace MediaBrowser.Server.Implementations.Sync
}
var target = GetSyncTargets(request.UserId)
- .First(i => string.Equals(request.TargetId, i.Id));
+ .FirstOrDefault(i => string.Equals(request.TargetId, i.Id));
+
+ if (target == null)
+ {
+ throw new ArgumentException("Sync target not found.");
+ }
var jobId = Guid.NewGuid().ToString("N");
@@ -80,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Sync
UserId = request.UserId,
UnwatchedOnly = request.UnwatchedOnly,
ItemLimit = request.ItemLimit,
- RequestedItemIds = request.ItemIds,
+ RequestedItemIds = request.ItemIds ?? new List<string> { },
DateCreated = DateTime.UtcNow,
DateLastModified = DateTime.UtcNow,
SyncNewContent = request.SyncNewContent,
@@ -106,21 +131,49 @@ namespace MediaBrowser.Server.Implementations.Sync
};
}
- public QueryResult<SyncJob> GetJobs(SyncJobQuery query)
+ public Task UpdateJob(SyncJob job)
+ {
+ // Get fresh from the db and only update the fields that are supported to be changed.
+ var instance = _repo.GetJob(job.Id);
+
+ instance.Name = job.Name;
+ instance.Quality = job.Quality;
+ instance.UnwatchedOnly = job.UnwatchedOnly;
+ instance.SyncNewContent = job.SyncNewContent;
+ instance.ItemLimit = job.ItemLimit;
+
+ return _repo.Update(instance);
+ }
+
+ public async Task<QueryResult<SyncJob>> GetJobs(SyncJobQuery query)
{
var result = _repo.GetJobs(query);
- result.Items.ForEach(FillMetadata);
+ foreach (var item in result.Items)
+ {
+ await FillMetadata(item).ConfigureAwait(false);
+ }
return result;
}
- private void FillMetadata(SyncJob job)
+ private async Task FillMetadata(SyncJob job)
{
var item = job.RequestedItemIds
.Select(_libraryManager.GetItemById)
.FirstOrDefault(i => i != null);
+ if (item == null)
+ {
+ var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder());
+
+ var user = _userManager.GetUserById(job.UserId);
+
+ item = (await processor
+ .GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
+ .FirstOrDefault();
+ }
+
if (item != null)
{
var hasSeries = item as IHasSeries;
@@ -136,13 +189,25 @@ namespace MediaBrowser.Server.Implementations.Sync
}
var primaryImage = item.GetImageInfo(ImageType.Primary, 0);
+ var itemWithImage = item;
+
+ if (primaryImage == null)
+ {
+ var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+
+ if (parentWithImage != null)
+ {
+ itemWithImage = parentWithImage;
+ primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0);
+ }
+ }
if (primaryImage != null)
{
try
{
- job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
- job.PrimaryImageItemId = item.Id.ToString("N");
+ job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary);
+ job.PrimaryImageItemId = itemWithImage.Id.ToString("N");
}
catch (Exception ex)
@@ -153,6 +218,44 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
+ private void FillMetadata(SyncJobItem jobItem)
+ {
+ var item = _libraryManager.GetItemById(jobItem.ItemId);
+
+ if (item == null)
+ {
+ return;
+ }
+
+ var primaryImage = item.GetImageInfo(ImageType.Primary, 0);
+ var itemWithImage = item;
+
+ if (primaryImage == null)
+ {
+ var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+
+ if (parentWithImage != null)
+ {
+ itemWithImage = parentWithImage;
+ primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0);
+ }
+ }
+
+ if (primaryImage != null)
+ {
+ try
+ {
+ jobItem.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary);
+ jobItem.PrimaryImageItemId = itemWithImage.Id.ToString("N");
+
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting image info", ex);
+ }
+ }
+ }
+
public Task CancelJob(string id)
{
return _repo.DeleteJob(id);
@@ -172,17 +275,23 @@ namespace MediaBrowser.Server.Implementations.Sync
private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
{
- var providerId = GetSyncProviderId(provider);
-
- return provider.GetSyncTargets().Select(i => new SyncTarget
+ return provider.GetSyncTargets(userId).Select(i => new SyncTarget
{
Name = i.Name,
- Id = GetSyncTargetId(providerId, i)
+ Id = GetSyncTargetId(provider, i)
});
}
- private string GetSyncTargetId(string providerId, SyncTarget target)
+ private string GetSyncTargetId(ISyncProvider provider, SyncTarget target)
{
+ var hasUniqueId = provider as IHasUniqueTargetIds;
+
+ if (hasUniqueId != null)
+ {
+ return target.Id;
+ }
+
+ var providerId = GetSyncProviderId(provider);
return (providerId + "-" + target.Id).GetMD5().ToString("N");
}
@@ -239,10 +348,21 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
+ if (item is LiveTvChannel || item is IChannelItem || item is ILiveTvRecording)
+ {
+ return false;
+ }
+
+ // It would be nice to support these later
+ if (item is Game || item is Book)
+ {
+ return false;
+ }
+
return true;
}
- return item.LocationType == LocationType.FileSystem || item is Season;
+ return item.LocationType == LocationType.FileSystem || item is Season || item is ILiveTvRecording;
}
private string GetDefaultName(BaseItem item)
@@ -270,12 +390,12 @@ namespace MediaBrowser.Server.Implementations.Sync
{
var jobItem = _repo.GetJobItem(id);
- jobItem.Status = SyncJobItemStatus.Completed;
+ jobItem.Status = SyncJobItemStatus.Synced;
jobItem.Progress = 100;
await _repo.Update(jobItem).ConfigureAwait(false);
- var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager);
+ var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder());
await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
}
@@ -287,7 +407,162 @@ namespace MediaBrowser.Server.Implementations.Sync
public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query)
{
- return _repo.GetJobItems(query);
+ var result = _repo.GetJobItems(query);
+
+ if (query.AddMetadata)
+ {
+ result.Items.ForEach(FillMetadata);
+ }
+
+ return result;
+ }
+
+ private SyncedItem GetJobItemInfo(SyncJobItem jobItem)
+ {
+ var job = _repo.GetJob(jobItem.JobId);
+
+ var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
+
+ var syncedItem = new SyncedItem
+ {
+ SyncJobId = jobItem.JobId,
+ SyncJobItemId = jobItem.Id,
+ ServerId = _appHost.SystemId,
+ UserId = job.UserId
+ };
+
+ var dtoOptions = new DtoOptions();
+
+ // Remove some bloat
+ dtoOptions.Fields.Remove(ItemFields.MediaStreams);
+ dtoOptions.Fields.Remove(ItemFields.IndexOptions);
+ dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
+ dtoOptions.Fields.Remove(ItemFields.OriginalPrimaryImageAspectRatio);
+ dtoOptions.Fields.Remove(ItemFields.Path);
+ dtoOptions.Fields.Remove(ItemFields.SeriesGenres);
+ dtoOptions.Fields.Remove(ItemFields.Settings);
+ dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+
+ syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions);
+
+ // TODO: this should be the media source of the transcoded output
+ syncedItem.Item.MediaSources = syncedItem.Item.MediaSources
+ .Where(i => string.Equals(i.Id, jobItem.MediaSourceId))
+ .ToList();
+
+ var mediaSource = syncedItem.Item.MediaSources
+ .FirstOrDefault(i => string.Equals(i.Id, jobItem.MediaSourceId));
+
+ // This will be null for items that are not audio/video
+ if (mediaSource == null)
+ {
+ syncedItem.OriginalFileName = Path.GetFileName(libraryItem.Path);
+ }
+ else
+ {
+ syncedItem.OriginalFileName = Path.GetFileName(mediaSource.Path);
+ }
+
+ return syncedItem;
+ }
+
+ public Task ReportOfflineAction(UserAction action)
+ {
+ return Task.FromResult(true);
+ }
+
+ public List<SyncedItem> GetReadySyncItems(string targetId)
+ {
+ var jobItemResult = GetJobItems(new SyncJobItemQuery
+ {
+ TargetId = targetId,
+ Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Transferring }
+ });
+
+ return jobItemResult.Items.Select(GetJobItemInfo)
+ .ToList();
+ }
+
+ public async Task<SyncDataResponse> SyncData(SyncDataRequest request)
+ {
+ var jobItemResult = GetJobItems(new SyncJobItemQuery
+ {
+ TargetId = request.TargetId,
+ Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Synced }
+ });
+
+ var response = new SyncDataResponse();
+
+ foreach (var jobItem in jobItemResult.Items)
+ {
+ if (request.LocalItemIds.Contains(jobItem.ItemId, StringComparer.OrdinalIgnoreCase))
+ {
+ var job = _repo.GetJob(jobItem.JobId);
+ var user = _userManager.GetUserById(job.UserId);
+
+ if (user == null)
+ {
+ // Tell the device to remove it since the user is gone now
+ response.ItemIdsToRemove.Add(jobItem.ItemId);
+ }
+ else if (job.UnwatchedOnly)
+ {
+ var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
+
+ if (IsLibraryItemAvailable(libraryItem))
+ {
+ if (libraryItem.IsPlayed(user) && libraryItem is Video)
+ {
+ // Tell the device to remove it since it has been played
+ response.ItemIdsToRemove.Add(jobItem.ItemId);
+ }
+ }
+ else
+ {
+ // Tell the device to remove it since it's no longer available
+ response.ItemIdsToRemove.Add(jobItem.ItemId);
+ }
+ }
+ }
+ else
+ {
+ // Content is no longer on the device
+ jobItem.Status = SyncJobItemStatus.RemovedFromDevice;
+ await _repo.Update(jobItem).ConfigureAwait(false);
+ }
+ }
+
+ // Now check each item that's on the device
+ foreach (var itemId in request.LocalItemIds)
+ {
+ // See if it's already marked for removal
+ if (response.ItemIdsToRemove.Contains(itemId, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ // If there isn't a sync job for this item, mark it for removal
+ if (!jobItemResult.Items.Any(i => string.Equals(itemId, i.ItemId, StringComparison.OrdinalIgnoreCase)))
+ {
+ response.ItemIdsToRemove.Add(itemId);
+ }
+ }
+
+ response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
+
+ return response;
+ }
+
+ private bool IsLibraryItemAvailable(BaseItem item)
+ {
+ if (item == null)
+ {
+ return false;
+ }
+
+ // TODO: Make sure it hasn't been deleted
+
+ return true;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
index 7825b9e9a..09c1b316e 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
@@ -24,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _deleteJobCommand;
+ private IDbCommand _deleteJobItemsCommand;
private IDbCommand _saveJobCommand;
private IDbCommand _saveJobItemCommand;
@@ -35,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public async Task Initialize()
{
- var dbFile = Path.Combine(_appPaths.DataPath, "sync6.db");
+ var dbFile = Path.Combine(_appPaths.DataPath, "sync10.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
@@ -44,7 +45,7 @@ namespace MediaBrowser.Server.Implementations.Sync
"create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
"create index if not exists idx_SyncJobs on SyncJobs(Id)",
- "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)",
+ "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)",
"create index if not exists idx_SyncJobItems on SyncJobs(Id)",
//pragmas
@@ -61,9 +62,13 @@ namespace MediaBrowser.Server.Implementations.Sync
private void PrepareStatements()
{
_deleteJobCommand = _connection.CreateCommand();
- _deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id; delete from SyncJobItems where JobId=@Id";
+ _deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id";
_deleteJobCommand.Parameters.Add(_deleteJobCommand, "@Id");
+ _deleteJobItemsCommand = _connection.CreateCommand();
+ _deleteJobItemsCommand.CommandText = "delete from SyncJobItems where JobId=@JobId";
+ _deleteJobItemsCommand.Parameters.Add(_deleteJobItemsCommand, "@JobId");
+
_saveJobCommand = _connection.CreateCommand();
_saveJobCommand.CommandText = "replace into SyncJobs (Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Quality, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)";
@@ -85,20 +90,22 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount");
_saveJobItemCommand = _connection.CreateCommand();
- _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)";
-
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Id");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@ItemId");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@JobId");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@OutputPath");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Status");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@TargetId");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@DateCreated");
- _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Progress");
+ _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)";
+
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemName");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSourceId");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobId");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@OutputPath");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Status");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TargetId");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@DateCreated");
+ _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Progress");
}
private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs";
- private const string BaseJobItemSelectText = "select Id, ItemId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems";
+ private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems";
public SyncJob GetJob(string id)
{
@@ -113,7 +120,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{
throw new ArgumentNullException("id");
}
-
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseJobSelectText + " where Id=@Id";
@@ -163,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.Sync
if (!reader.IsDBNull(7))
{
- info.RequestedItemIds = reader.GetString(7).Split(',').ToList();
+ info.RequestedItemIds = reader.GetString(7).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
if (!reader.IsDBNull(8))
@@ -221,7 +228,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobCommand.GetParameter(index++).Value = job.TargetId;
_saveJobCommand.GetParameter(index++).Value = job.Name;
_saveJobCommand.GetParameter(index++).Value = job.Quality;
- _saveJobCommand.GetParameter(index++).Value = job.Status;
+ _saveJobCommand.GetParameter(index++).Value = job.Status.ToString();
_saveJobCommand.GetParameter(index++).Value = job.Progress;
_saveJobCommand.GetParameter(index++).Value = job.UserId;
_saveJobCommand.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray());
@@ -289,11 +296,14 @@ namespace MediaBrowser.Server.Implementations.Sync
var index = 0;
_deleteJobCommand.GetParameter(index++).Value = new Guid(id);
-
_deleteJobCommand.Transaction = transaction;
-
_deleteJobCommand.ExecuteNonQuery();
+ index = 0;
+ _deleteJobItemsCommand.GetParameter(index++).Value = id;
+ _deleteJobItemsCommand.Transaction = transaction;
+ _deleteJobItemsCommand.ExecuteNonQuery();
+
transaction.Commit();
}
catch (OperationCanceledException)
@@ -357,6 +367,11 @@ namespace MediaBrowser.Server.Implementations.Sync
whereClauses.Add("TargetId=@TargetId");
cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId;
}
+ if (!string.IsNullOrWhiteSpace(query.UserId))
+ {
+ whereClauses.Add("UserId=@UserId");
+ cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
+ }
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
@@ -457,23 +472,12 @@ namespace MediaBrowser.Server.Implementations.Sync
whereClauses.Add("TargetId=@TargetId");
cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId;
}
- if (query.Status.HasValue)
- {
- whereClauses.Add("Status=@Status");
- cmd.Parameters.Add(cmd, "@Status", DbType.String).Value = query.Status.Value.ToString();
- }
- if (query.IsCompleted.HasValue)
+ if (query.Statuses.Count > 0)
{
- if (query.IsCompleted.Value)
- {
- whereClauses.Add("Status=@Status");
- }
- else
- {
- whereClauses.Add("Status<>@Status");
- }
- cmd.Parameters.Add(cmd, "@Status", DbType.String).Value = SyncJobStatus.Completed.ToString();
+ var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray());
+
+ whereClauses.Add(string.Format("Status in ({0})", statuses));
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
@@ -549,9 +553,11 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobItemCommand.GetParameter(index++).Value = new Guid(jobItem.Id);
_saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemId;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemName;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath;
- _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status.ToString();
_saveJobItemCommand.GetParameter(index++).Value = jobItem.TargetId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.DateCreated;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.Progress;
@@ -598,29 +604,40 @@ namespace MediaBrowser.Server.Implementations.Sync
var info = new SyncJobItem
{
Id = reader.GetGuid(0).ToString("N"),
- ItemId = reader.GetString(1),
- JobId = reader.GetString(2)
+ ItemId = reader.GetString(1)
};
+ if (!reader.IsDBNull(2))
+ {
+ info.ItemName = reader.GetString(2);
+ }
+
if (!reader.IsDBNull(3))
{
- info.OutputPath = reader.GetString(3);
+ info.MediaSourceId = reader.GetString(3);
}
- if (!reader.IsDBNull(4))
+ info.JobId = reader.GetString(4);
+
+ if (!reader.IsDBNull(5))
+ {
+ info.OutputPath = reader.GetString(5);
+ }
+
+ if (!reader.IsDBNull(6))
{
- info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(4), true);
+ info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(6), true);
}
- info.TargetId = reader.GetString(5);
+ info.TargetId = reader.GetString(7);
- info.DateCreated = reader.GetDateTime(6);
+ info.DateCreated = reader.GetDateTime(8);
- if (!reader.IsDBNull(7))
+ if (!reader.IsDBNull(9))
{
- info.Progress = reader.GetDouble(7);
+ info.Progress = reader.GetDouble(9);
}
-
+
return info;
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
index df03ab6f7..c2925551b 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Sync;
+using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@@ -16,19 +18,23 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly ISyncManager _syncManager;
private readonly ILogger _logger;
private readonly IUserManager _userManager;
+ private readonly ITVSeriesManager _tvSeriesManager;
+ private readonly IMediaEncoder _mediaEncoder;
- public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager)
+ public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder)
{
_libraryManager = libraryManager;
_syncRepo = syncRepo;
_syncManager = syncManager;
_logger = logger;
_userManager = userManager;
+ _tvSeriesManager = tvSeriesManager;
+ _mediaEncoder = mediaEncoder;
}
public string Name
{
- get { return "Sync"; }
+ get { return "Sync preparation"; }
}
public string Description
@@ -46,7 +52,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
- return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager).Sync(progress,
+ return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder).Sync(progress,
cancellationToken);
}