Exemple #1
0
        public async Task Sync(IServerSyncProvider provider,
                               ISyncDataProvider dataProvider,
                               SyncTarget target,
                               IProgress <double> progress,
                               CancellationToken cancellationToken)
        {
            var serverId   = _appHost.SystemId;
            var serverName = _appHost.FriendlyName;

            await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false);

            progress.Report(3);

            var innerProgress = new ActionableProgress <double>();

            innerProgress.RegisterAction(pct =>
            {
                var totalProgress = pct * .97;
                totalProgress    += 1;
                progress.Report(totalProgress);
            });
            await GetNewMedia(provider, dataProvider, target, serverId, serverName, innerProgress, cancellationToken);

            // Do the data sync twice so the server knows what was removed from the device
            await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false);

            progress.Report(100);
        }
Exemple #2
0
        private async Task RemoveItem(IServerSyncProvider provider,
                                      ISyncDataProvider dataProvider,
                                      string serverId,
                                      string syncJobItemId,
                                      SyncTarget target,
                                      CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId);

            foreach (var localItem in localItems)
            {
                var files = localItem.AdditionalFiles.ToList();

                foreach (var file in files)
                {
                    _logger.Debug("Removing {0} from {1}.", file, target.Name);
                    await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false);
                }

                _logger.Debug("Removing {0} from {1}.", localItem.FileId, target.Name);
                await provider.DeleteFile(localItem.FileId, target, cancellationToken).ConfigureAwait(false);

                await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false);
            }
        }
Exemple #3
0
        private async Task SyncData(IServerSyncProvider provider,
                                    string serverId,
                                    SyncTarget target,
                                    CancellationToken cancellationToken)
        {
            var localIds = await provider.GetServerItemIds(serverId, target, cancellationToken).ConfigureAwait(false);

            var result = await _syncManager.SyncData(new SyncDataRequest
            {
                TargetId     = target.Id,
                LocalItemIds = localIds
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            foreach (var itemIdToRemove in result.ItemIdsToRemove)
            {
                try
                {
                    await RemoveItem(provider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error deleting item from sync target. Id: {0}", ex, itemIdToRemove);
                }
            }
        }
Exemple #4
0
        public async Task Sync(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            SyncTarget target,
            IProgress<double> progress,
            CancellationToken cancellationToken)
        {
            var serverId = _appHost.SystemId;
            var serverName = _appHost.FriendlyName;

            await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false);
            progress.Report(3);

            var innerProgress = new ActionableProgress<double>();
            innerProgress.RegisterAction(pct =>
            {
                var totalProgress = pct * .97;
                totalProgress += 1;
                progress.Report(totalProgress);
            });
            await GetNewMedia(provider, dataProvider, target, serverId, serverName, innerProgress, cancellationToken);

            // Do the data sync twice so the server knows what was removed from the device
            await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false);
            
            progress.Report(100);
        }
Exemple #5
0
 private Task RemoveItem(IServerSyncProvider provider,
                         string serverId,
                         string itemId,
                         SyncTarget target,
                         CancellationToken cancellationToken)
 {
     return(provider.DeleteItem(serverId, itemId, target, cancellationToken));
 }
 public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, string serverId, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths)
 {
     _logger     = logger;
     _json       = json;
     _provider   = provider;
     _target     = target;
     _fileSystem = fileSystem;
     _appPaths   = appPaths;
     _serverId   = serverId;
 }
Exemple #7
0
        private string[] GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target)
        {
            var filename = GetSubtitleSaveFileName(item, stream.Language, stream.IsForced) + "." + stream.Codec.ToLower();

            var pathParts = item.LocalPath.Split(PathSeparatorChar);
            var list      = pathParts.Take(pathParts.Length - 1).ToList();

            list.Add(filename);

            return(list.ToArray());
        }
Exemple #8
0
        private string GetLocalFileName(IServerSyncProvider provider, BaseItemDto item, string originalFileName)
        {
            var filename = originalFileName;

            if (string.IsNullOrWhiteSpace(filename))
            {
                filename = item.Name;
            }

            return(GetValidFilename(provider, filename));
        }
Exemple #9
0
 public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider)
 {
     _logger               = logger;
     _json                 = json;
     _provider             = provider;
     _target               = target;
     _fileSystem           = fileSystem;
     _appPaths             = appPaths;
     _memoryStreamProvider = memoryStreamProvider;
     _appHost              = appHost;
 }
Exemple #10
0
        private async Task <SyncedFileInfo> SendFile(IServerSyncProvider provider, string inputPath, string[] pathParts, SyncTarget target, SyncOptions options, IProgress <double> progress, CancellationToken cancellationToken)
        {
            _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, string.Join("/", pathParts));
            using (var fileStream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
            {
                Stream stream = fileStream;

                if (options.UploadSpeedLimitBytes > 0 && provider is IRemoteSyncProvider)
                {
                    stream = new ThrottledStream(stream, options.UploadSpeedLimitBytes);
                }

                return(await provider.SendFile(stream, pathParts, target, progress, cancellationToken).ConfigureAwait(false));
            }
        }
Exemple #11
0
        private async Task GetNewMedia(IServerSyncProvider provider,
                                       ISyncDataProvider dataProvider,
                                       SyncTarget target,
                                       string serverId,
                                       string serverName,
                                       IProgress <double> progress,
                                       CancellationToken cancellationToken)
        {
            var jobItems = await _syncManager.GetReadySyncItems(target.Id).ConfigureAwait(false);

            var    numComplete     = 0;
            double startingPercent = 0;
            double percentPerItem  = 1;

            if (jobItems.Count > 0)
            {
                percentPerItem /= jobItems.Count;
            }

            foreach (var jobItem in jobItems)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var currentPercent = startingPercent;
                var innerProgress  = new ActionableProgress <double>();
                innerProgress.RegisterAction(pct =>
                {
                    var totalProgress = pct * percentPerItem;
                    totalProgress    += currentPercent;
                    progress.Report(totalProgress);
                });

                try
                {
                    await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error syncing item", ex);
                }

                numComplete++;
                startingPercent  = numComplete;
                startingPercent /= jobItems.Count;
                startingPercent *= 100;
                progress.Report(startingPercent);
            }
        }
Exemple #12
0
        private async Task SyncData(IServerSyncProvider provider,
                                    ISyncDataProvider dataProvider,
                                    string serverId,
                                    SyncTarget target,
                                    CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false);

            var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false);

            var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList();

            var jobItemIds = new List <string>();

            foreach (var localItem in localItems)
            {
                // TODO: Remove this after a while
                if (string.IsNullOrWhiteSpace(localItem.FileId))
                {
                    jobItemIds.Add(localItem.SyncJobItemId);
                }
                else if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase))
                {
                    jobItemIds.Add(localItem.SyncJobItemId);
                }
            }

            var result = await _syncManager.SyncData(new SyncDataRequest
            {
                TargetId       = target.Id,
                SyncJobItemIds = jobItemIds
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            foreach (var itemIdToRemove in result.ItemIdsToRemove)
            {
                try
                {
                    await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove);
                }
            }
        }
Exemple #13
0
        private async Task GetItem(IServerSyncProvider provider,
                                   SyncTarget target,
                                   string serverId,
                                   SyncedItem jobItem,
                                   IProgress <double> progress,
                                   CancellationToken cancellationToken)
        {
            var libraryItem         = jobItem.Item;
            var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId);

            var fileTransferProgress = new ActionableProgress <double>();

            fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));

            await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id);

            var       transferSuccess   = false;
            Exception transferException = null;

            try
            {
                //await provider.TransferItemFile(serverId, libraryItem.Id, internalSyncJobItem.OutputPath, target, cancellationToken)
                //        .ConfigureAwait(false);

                progress.Report(92);

                transferSuccess = true;

                progress.Report(99);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error transferring sync job file", ex);
                transferException = ex;
            }

            if (transferSuccess)
            {
                await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false);
            }
            else
            {
                await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false);

                throw transferException;
            }
        }
Exemple #14
0
        private List <string> GetDirectoryPath(IServerSyncProvider provider, string syncJobId, BaseItemDto item, string serverId)
        {
            var parts = new List <string>
            {
                serverId,
                syncJobId
            };

            if (item.IsType("episode"))
            {
                parts.Add("TV");
                if (!string.IsNullOrWhiteSpace(item.SeriesName))
                {
                    parts.Add(item.SeriesName);
                }
            }
            else if (item.IsVideo)
            {
                parts.Add("Videos");
                parts.Add(item.Name);
            }
            else if (item.IsAudio)
            {
                parts.Add("Music");

                if (!string.IsNullOrWhiteSpace(item.AlbumArtist))
                {
                    parts.Add(item.AlbumArtist);
                }

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }
            else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase))
            {
                parts.Add("Photos");

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }

            return(parts.Select(i => GetValidFilename(provider, i)).ToList());
        }
Exemple #15
0
        private async Task SyncData(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            string serverId,
            SyncTarget target,
            CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false);
            var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false);
            var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList();

            var jobItemIds = new List<string>();

            foreach (var localItem in localItems)
            {
                // TODO: Remove this after a while
                if (string.IsNullOrWhiteSpace(localItem.FileId))
                {
                    jobItemIds.Add(localItem.SyncJobItemId);
                }
                else if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase))
                {
                    jobItemIds.Add(localItem.SyncJobItemId);
                }
            }

            var result = await _syncManager.SyncData(new SyncDataRequest
            {
                TargetId = target.Id,
                SyncJobItemIds = jobItemIds

            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            foreach (var itemIdToRemove in result.ItemIdsToRemove)
            {
                try
                {
                    await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove);
                }
            }
        }
Exemple #16
0
        private async Task RemoveItem(IServerSyncProvider provider,
                                      ISyncDataProvider dataProvider,
                                      string serverId,
                                      string itemId,
                                      SyncTarget target,
                                      CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetCachedItems(target, serverId, itemId);

            foreach (var localItem in localItems)
            {
                var files = await GetFiles(provider, localItem, target, cancellationToken);

                foreach (var file in files)
                {
                    await provider.DeleteFile(file.Path, target, cancellationToken).ConfigureAwait(false);
                }

                await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false);
            }
        }
        private void AddMediaSource(List <MediaSourceInfo> list,
                                    LocalItem item,
                                    MediaSourceInfo mediaSource,
                                    IServerSyncProvider provider,
                                    SyncTarget target)
        {
            SetStaticMediaSourceInfo(item, mediaSource);

            var requiresDynamicAccess = provider as IHasDynamicAccess;

            if (requiresDynamicAccess != null)
            {
                mediaSource.RequiresOpening = true;

                var keyList = new List <string>();
                keyList.Add(provider.GetType().FullName.GetMD5().ToString("N"));
                keyList.Add(target.Id.GetMD5().ToString("N"));
                keyList.Add(item.Id);
                mediaSource.OpenToken = string.Join(StreamIdDelimeterString, keyList.ToArray());
            }

            list.Add(mediaSource);
        }
        private void AddMediaSource(List<MediaSourceInfo> list,
            LocalItem item,
            MediaSourceInfo mediaSource,
            IServerSyncProvider provider,
            SyncTarget target)
        {
            SetStaticMediaSourceInfo(item, mediaSource);

            var requiresDynamicAccess = provider as IHasDynamicAccess;

            if (requiresDynamicAccess != null)
            {
                mediaSource.RequiresOpening = true;

                var keyList = new List<string>();
                keyList.Add(provider.GetType().FullName.GetMD5().ToString("N"));
                keyList.Add(target.Id.GetMD5().ToString("N"));
                keyList.Add(item.Id);
                mediaSource.OpenToken = string.Join(StreamIdDelimeterString, keyList.ToArray());
            }

            list.Add(mediaSource);
        }
Exemple #19
0
        public LocalItem CreateLocalItem(IServerSyncProvider provider, string syncJobId, string syncJobItemId, SyncTarget target, BaseItemDto libraryItem, string serverId, string originalFileName)
        {
            var path = GetDirectoryPath(provider, syncJobId, libraryItem, serverId);

            path.Add(GetLocalFileName(provider, libraryItem, originalFileName));

            var localPath = provider.GetFullPath(path, target);

            foreach (var mediaSource in libraryItem.MediaSources)
            {
                mediaSource.Path     = localPath;
                mediaSource.Protocol = MediaProtocol.File;
            }

            return(new LocalItem
            {
                Item = libraryItem,
                ItemId = libraryItem.Id,
                ServerId = serverId,
                LocalPath = localPath,
                Id = GetLocalId(syncJobItemId, libraryItem.Id)
            });
        }
Exemple #20
0
        public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName)
        {
            var path = GetDirectoryPath(provider, job, syncedItem, libraryItem, serverName);

            path.Add(GetLocalFileName(provider, libraryItem, originalFileName));

            var localPath = string.Join(PathSeparatorString, path.ToArray());

            foreach (var mediaSource in libraryItem.MediaSources)
            {
                mediaSource.Path     = localPath;
                mediaSource.Protocol = MediaProtocol.File;
            }

            return(new LocalItem
            {
                Item = libraryItem,
                ItemId = libraryItem.Id,
                ServerId = serverId,
                LocalPath = localPath,
                Id = GetLocalId(syncedItem.SyncJobItemId, libraryItem.Id),
                SyncJobItemId = syncedItem.SyncJobItemId
            });
        }
Exemple #21
0
        private async Task GetItem(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            SyncTarget target,
            string serverId,
            string serverName,
            SyncedItem jobItem,
            IProgress<double> progress,
            CancellationToken cancellationToken)
        {
            var libraryItem = jobItem.Item;
            var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId);
            var internalSyncJob = _syncManager.GetJob(jobItem.SyncJobId);

            var localItem = CreateLocalItem(provider, jobItem, internalSyncJob, target, libraryItem, serverId, serverName, jobItem.OriginalFileName);

            await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id);

            var transferSuccess = false;
            Exception transferException = null;

            var options = _config.GetSyncOptions();

            try
            {
                var fileTransferProgress = new ActionableProgress<double>();
                fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));

                var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false);

                if (localItem.Item.MediaSources != null)
                {
                    var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
                    if (mediaSource != null)
                    {
                        mediaSource.Path = sendFileResult.Path;
                        mediaSource.Protocol = sendFileResult.Protocol;
                        mediaSource.RequiredHttpHeaders = sendFileResult.RequiredHttpHeaders;
                        mediaSource.SupportsTranscoding = false;
                    }
                }

                localItem.FileId = sendFileResult.Id;

                // Create db record
                await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);

                if (localItem.Item.MediaSources != null)
                {
                    var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
                    if (mediaSource != null)
                    {
                        await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false);
                    }
                }

                progress.Report(92);

                transferSuccess = true;

                progress.Report(99);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error transferring sync job file", ex);
                transferException = ex;
            }

            if (transferSuccess)
            {
                await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false);
            }
            else
            {
                await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false);

                throw transferException;
            }
        }
Exemple #22
0
        private async Task<SyncedFileInfo> SendFile(IServerSyncProvider provider, string inputPath, string[] pathParts, SyncTarget target, SyncOptions options, IProgress<double> progress, CancellationToken cancellationToken)
        {
            _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, string.Join("/", pathParts));
            var supportsDirectCopy = provider as ISupportsDirectCopy;
            if (supportsDirectCopy != null)
            {
                return await supportsDirectCopy.SendFile(inputPath, pathParts, target, progress, cancellationToken).ConfigureAwait(false);
            }

            using (var fileStream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
            {
                Stream stream = fileStream;

                if (options.UploadSpeedLimitBytes > 0 && provider is IRemoteSyncProvider)
                {
                    stream = new ThrottledStream(stream, options.UploadSpeedLimitBytes);
                }

                return await provider.SendFile(stream, pathParts, target, progress, cancellationToken).ConfigureAwait(false);
            }
        }
Exemple #23
0
        private List <string> GetDirectoryPath(IServerSyncProvider provider, SyncJob job, SyncedItem syncedItem, BaseItemDto item, string serverName)
        {
            var parts = new List <string>
            {
                serverName
            };

            var profileOption = _syncManager.GetProfileOptions(job.TargetId)
                                .FirstOrDefault(i => string.Equals(i.Id, job.Profile, StringComparison.OrdinalIgnoreCase));

            string name;

            if (profileOption != null && !string.IsNullOrWhiteSpace(profileOption.Name))
            {
                name = profileOption.Name;

                if (job.Bitrate.HasValue)
                {
                    name += "-" + job.Bitrate.Value.ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    var qualityOption = _syncManager.GetQualityOptions(job.TargetId)
                                        .FirstOrDefault(i => string.Equals(i.Id, job.Quality, StringComparison.OrdinalIgnoreCase));

                    if (qualityOption != null && !string.IsNullOrWhiteSpace(qualityOption.Name))
                    {
                        name += "-" + qualityOption.Name;
                    }
                }
            }
            else
            {
                name = syncedItem.SyncJobName + "-" + syncedItem.SyncJobDateCreated
                       .ToLocalTime()
                       .ToString("g")
                       .Replace(" ", "-");
            }

            name = GetValidFilename(provider, name);
            parts.Add(name);

            if (item.IsType("episode"))
            {
                parts.Add("TV");
                if (!string.IsNullOrWhiteSpace(item.SeriesName))
                {
                    parts.Add(item.SeriesName);
                }
            }
            else if (item.IsVideo)
            {
                parts.Add("Videos");
                parts.Add(item.Name);
            }
            else if (item.IsAudio)
            {
                parts.Add("Music");

                if (!string.IsNullOrWhiteSpace(item.AlbumArtist))
                {
                    parts.Add(item.AlbumArtist);
                }

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }
            else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase))
            {
                parts.Add("Photos");

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }

            return(parts.Select(i => GetValidFilename(provider, i)).ToList());
        }
Exemple #24
0
        private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken)
        {
            var failedSubtitles = new List <MediaStream>();
            var requiresSave    = false;

            foreach (var mediaStream in mediaSource.MediaStreams
                     .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal)
                     .ToList())
            {
                try
                {
                    var remotePath     = GetRemoteSubtitlePath(localItem, mediaStream, provider, target);
                    var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress <double>(), cancellationToken).ConfigureAwait(false);

                    // This is the path that will be used when talking to the provider
                    mediaStream.ExternalId = sendFileResult.Id;

                    // Keep track of all additional files for cleanup later.
                    localItem.AdditionalFiles.Add(sendFileResult.Id);

                    // This is the public path clients will use
                    mediaStream.Path = sendFileResult.Path;
                    requiresSave     = true;
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending subtitle stream", ex);
                    failedSubtitles.Add(mediaStream);
                }
            }

            if (failedSubtitles.Count > 0)
            {
                mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList();
                requiresSave             = true;
            }

            if (requiresSave)
            {
                await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);
            }
        }
Exemple #25
0
        private async Task GetItem(IServerSyncProvider provider,
                                   ISyncDataProvider dataProvider,
                                   SyncTarget target,
                                   string serverId,
                                   string serverName,
                                   SyncedItem jobItem,
                                   IProgress <double> progress,
                                   CancellationToken cancellationToken)
        {
            var libraryItem         = jobItem.Item;
            var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId);
            var internalSyncJob     = _syncManager.GetJob(jobItem.SyncJobId);

            var localItem = CreateLocalItem(provider, jobItem, internalSyncJob, target, libraryItem, serverId, serverName, jobItem.OriginalFileName);

            await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id);

            var       transferSuccess   = false;
            Exception transferException = null;

            var options = _config.GetSyncOptions();

            try
            {
                var fileTransferProgress = new ActionableProgress <double>();
                fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));

                var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false);

                if (localItem.Item.MediaSources != null)
                {
                    var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
                    if (mediaSource != null)
                    {
                        mediaSource.Path                = sendFileResult.Path;
                        mediaSource.Protocol            = sendFileResult.Protocol;
                        mediaSource.RequiredHttpHeaders = sendFileResult.RequiredHttpHeaders;
                        mediaSource.SupportsTranscoding = false;
                    }
                }

                localItem.FileId = sendFileResult.Id;

                // Create db record
                await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);

                if (localItem.Item.MediaSources != null)
                {
                    var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
                    if (mediaSource != null)
                    {
                        await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false);
                    }
                }

                progress.Report(92);

                transferSuccess = true;

                progress.Report(99);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error transferring sync job file", ex);
                transferException = ex;
            }

            if (transferSuccess)
            {
                await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false);
            }
            else
            {
                await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false);

                throw transferException;
            }
        }
Exemple #26
0
        private async Task RemoveItem(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            string serverId,
            string syncJobItemId,
            SyncTarget target,
            CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId);

            foreach (var localItem in localItems)
            {
                var files = localItem.AdditionalFiles.ToList();

                foreach (var file in files)
                {
                    _logger.Debug("Removing {0} from {1}.", file, target.Name);
                    await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false);
                }

                await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false);
            }
        }
Exemple #27
0
 public ISyncDataProvider GetDataProvider(IServerSyncProvider provider, SyncTarget target)
 {
     return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths));
 }
Exemple #28
0
        private async Task RemoveItem(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            string serverId,
            string syncJobItemId,
            SyncTarget target,
            CancellationToken cancellationToken)
        {
            var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId);

            foreach (var localItem in localItems)
            {
                var files = localItem.AdditionalFiles.ToList();

                // TODO: Remove this. Have to check it for now since this is a new property
                if (!string.IsNullOrWhiteSpace(localItem.FileId))
                {
                    files.Insert(0, localItem.FileId);
                }

                foreach (var file in files)
                {
                    _logger.Debug("Removing {0} from {1}.", file, target.Name);
                    await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false);
                }

                await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false);
            }
        }
Exemple #29
0
        public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName)
        {
            var path = GetDirectoryPath(provider, job, syncedItem, libraryItem, serverName);
            path.Add(GetLocalFileName(provider, libraryItem, originalFileName));

            var localPath = string.Join(PathSeparatorString, path.ToArray());

            foreach (var mediaSource in libraryItem.MediaSources)
            {
                mediaSource.Path = localPath;
                mediaSource.Protocol = MediaProtocol.File;
            }

            return new LocalItem
            {
                Item = libraryItem,
                ItemId = libraryItem.Id,
                ServerId = serverId,
                LocalPath = localPath,
                Id = GetLocalId(syncedItem.SyncJobItemId, libraryItem.Id),
                SyncJobItemId = syncedItem.SyncJobItemId
            };
        }
Exemple #30
0
 private string GetValidFilename(IServerSyncProvider provider, string filename)
 {
     // We can always add this method to the sync provider if it's really needed
     return _fileSystem.GetValidFilename(filename);
 }
Exemple #31
0
        private string GetLocalFileName(IServerSyncProvider provider, BaseItemDto item, string originalFileName)
        {
            var filename = originalFileName;

            if (string.IsNullOrWhiteSpace(filename))
            {
                filename = item.Name;
            }

            return GetValidFilename(provider, filename);
        }
Exemple #32
0
        private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken)
        {
            var failedSubtitles = new List<MediaStream>();
            var requiresSave = false;

            foreach (var mediaStream in mediaSource.MediaStreams
                .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal)
                .ToList())
            {
                try
                {
                    var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target);
                    var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress<double>(), cancellationToken).ConfigureAwait(false);

                    // This is the path that will be used when talking to the provider
                    mediaStream.ExternalId = sendFileResult.Id;

                    // Keep track of all additional files for cleanup later.
                    localItem.AdditionalFiles.Add(sendFileResult.Id);

                    // This is the public path clients will use
                    mediaStream.Path = sendFileResult.Path;
                    requiresSave = true;
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending subtitle stream", ex);
                    failedSubtitles.Add(mediaStream);
                }
            }

            if (failedSubtitles.Count > 0)
            {
                mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList();
                requiresSave = true;
            }

            if (requiresSave)
            {
                await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);
            }
        }
Exemple #33
0
        private List<string> GetDirectoryPath(IServerSyncProvider provider, SyncJob job, SyncedItem syncedItem, BaseItemDto item, string serverName)
        {
            var parts = new List<string>
            {
                serverName
            };

            var profileOption = _syncManager.GetProfileOptions(job.TargetId)
                .FirstOrDefault(i => string.Equals(i.Id, job.Profile, StringComparison.OrdinalIgnoreCase));

            string name;

            if (profileOption != null && !string.IsNullOrWhiteSpace(profileOption.Name))
            {
                name = profileOption.Name;

                if (job.Bitrate.HasValue)
                {
                    name += "-" + job.Bitrate.Value.ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    var qualityOption = _syncManager.GetQualityOptions(job.TargetId)
                        .FirstOrDefault(i => string.Equals(i.Id, job.Quality, StringComparison.OrdinalIgnoreCase));

                    if (qualityOption != null && !string.IsNullOrWhiteSpace(qualityOption.Name))
                    {
                        name += "-" + qualityOption.Name;
                    }
                }
            }
            else
            {
                name = syncedItem.SyncJobName + "-" + syncedItem.SyncJobDateCreated
                   .ToLocalTime()
                   .ToString("g")
                   .Replace(" ", "-");
            }

            name = GetValidFilename(provider, name);
            parts.Add(name);

            if (item.IsType("episode"))
            {
                parts.Add("TV");
                if (!string.IsNullOrWhiteSpace(item.SeriesName))
                {
                    parts.Add(item.SeriesName);
                }
            }
            else if (item.IsVideo)
            {
                parts.Add("Videos");
                parts.Add(item.Name);
            }
            else if (item.IsAudio)
            {
                parts.Add("Music");

                if (!string.IsNullOrWhiteSpace(item.AlbumArtist))
                {
                    parts.Add(item.AlbumArtist);
                }

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }
            else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase))
            {
                parts.Add("Photos");

                if (!string.IsNullOrWhiteSpace(item.Album))
                {
                    parts.Add(item.Album);
                }
            }

            return parts.Select(i => GetValidFilename(provider, i)).ToList();
        }
Exemple #34
0
 private string GetValidFilename(IServerSyncProvider provider, string filename)
 {
     // We can always add this method to the sync provider if it's really needed
     return(_fileSystem.GetValidFilename(filename));
 }
Exemple #35
0
        private async Task GetNewMedia(IServerSyncProvider provider,
            ISyncDataProvider dataProvider,
            SyncTarget target,
            string serverId,
            string serverName,
            IProgress<double> progress,
            CancellationToken cancellationToken)
        {
            var jobItems = await _syncManager.GetReadySyncItems(target.Id).ConfigureAwait(false);

            var numComplete = 0;
            double startingPercent = 0;
            double percentPerItem = 1;
            if (jobItems.Count > 0)
            {
                percentPerItem /= jobItems.Count;
            }

            foreach (var jobItem in jobItems)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var currentPercent = startingPercent;
                var innerProgress = new ActionableProgress<double>();
                innerProgress.RegisterAction(pct =>
                {
                    var totalProgress = pct * percentPerItem;
                    totalProgress += currentPercent;
                    progress.Report(totalProgress);
                });

                try
                {
                    await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error syncing item", ex);
                }

                numComplete++;
                startingPercent = numComplete;
                startingPercent /= jobItems.Count;
                startingPercent *= 100;
                progress.Report(startingPercent);
            }
        }
Exemple #36
0
 public ISyncDataProvider GetDataProvider(IServerSyncProvider provider, SyncTarget target)
 {
     return(_dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths)));
 }
Exemple #37
0
        private string[] GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target)
        {
            var filename = GetSubtitleSaveFileName(item, stream.Language, stream.IsForced) + "." + stream.Codec.ToLower();

            var pathParts = item.LocalPath.Split(PathSeparatorChar);
            var list = pathParts.Take(pathParts.Length - 1).ToList();
            list.Add(filename);

            return list.ToArray();
        }