diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d7a69ceb22..809d1f6f46 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -393,6 +393,7 @@ + diff --git a/MediaBrowser.Controller/Sync/IRequiresDynamicAccess.cs b/MediaBrowser.Controller/Sync/IRequiresDynamicAccess.cs new file mode 100644 index 0000000000..820a1dce08 --- /dev/null +++ b/MediaBrowser.Controller/Sync/IRequiresDynamicAccess.cs @@ -0,0 +1,18 @@ +using MediaBrowser.Model.Sync; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Sync +{ + public interface IRequiresDynamicAccess + { + /// + /// Gets the file information. + /// + /// The remote path. + /// The target. + /// The cancellation token. + /// Task<SendFileResult>. + Task GetFileInfo(string remotePath, SyncTarget target, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs index abf884e9d5..9cccd41509 100644 --- a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs +++ b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs @@ -54,14 +54,5 @@ namespace MediaBrowser.Controller.Sync /// The target. /// System.String. string GetParentDirectoryPath(string path, SyncTarget target); - - /// - /// Gets the file system entries. - /// - /// The path. - /// The target. - /// The cancellation token. - /// Task<List<DeviceFileInfo>>. - Task> GetFileSystemEntries(string path, SyncTarget target, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 4af32bb500..66fb486284 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -168,6 +168,12 @@ namespace MediaBrowser.Model.Entities /// The filename. public string Path { get; set; } + /// + /// Gets or sets the external identifier. + /// + /// The external identifier. + public string ExternalId { get; set; } + /// /// Gets or sets the pixel format. /// diff --git a/MediaBrowser.Model/Sync/LocalItem.cs b/MediaBrowser.Model/Sync/LocalItem.cs index c6a10298fe..37f605a590 100644 --- a/MediaBrowser.Model/Sync/LocalItem.cs +++ b/MediaBrowser.Model/Sync/LocalItem.cs @@ -35,9 +35,15 @@ namespace MediaBrowser.Model.Sync /// /// The user ids with access. public List UserIdsWithAccess { get; set; } + /// + /// Gets or sets the additional files. + /// + /// The additional files. + public List AdditionalFiles { get; set; } public LocalItem() { + AdditionalFiles = new List(); UserIdsWithAccess = new List(); } } diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index cac0e15546..befddabd8a 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -215,6 +215,13 @@ namespace MediaBrowser.Server.Implementations.Sync var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target); var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, new Progress(), cancellationToken).ConfigureAwait(false); + // This is the path that will be used when talking to the provider + mediaStream.ExternalId = remotePath; + + // Keep track of all additional files for cleanup later. + localItem.AdditionalFiles.Add(remotePath); + + // This is the public path clients will use mediaStream.Path = sendFileResult.Path; requiresSave = true; } @@ -280,13 +287,14 @@ namespace MediaBrowser.Server.Implementations.Sync foreach (var localItem in localItems) { - var files = await GetFiles(provider, localItem, target, cancellationToken); + var files = localItem.AdditionalFiles.ToList(); + files.Insert(0, localItem.LocalPath); foreach (var file in files) { - _logger.Debug("Removing {0} from {1}.", file.Path, target.Name); + _logger.Debug("Removing {0} from {1}.", file, target.Name); - await provider.DeleteFile(file.Path, target, cancellationToken).ConfigureAwait(false); + await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false); } await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); @@ -417,43 +425,5 @@ namespace MediaBrowser.Server.Implementations.Sync // We can always add this method to the sync provider if it's really needed return _fileSystem.GetValidFilename(filename); } - - private async Task> GetFiles(IServerSyncProvider provider, LocalItem item, SyncTarget target, CancellationToken cancellationToken) - { - var path = item.LocalPath; - path = provider.GetParentDirectoryPath(path, target); - - var list = await provider.GetFileSystemEntries(path, target, cancellationToken).ConfigureAwait(false); - - var itemFiles = new List(); - - var name = Path.GetFileNameWithoutExtension(item.LocalPath); - - foreach (var file in list.Where(f => f.Name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)) - { - var itemFile = new ItemFileInfo - { - Path = file.Path, - Name = file.Name - }; - - if (IsSubtitleFile(file.Name)) - { - itemFile.Type = ItemFileType.Subtitles; - } - - itemFiles.Add(itemFile); - } - - return itemFiles; - } - - private static readonly string[] SupportedSubtitleExtensions = { ".srt", ".vtt" }; - private bool IsSubtitleFile(string path) - { - var ext = Path.GetExtension(path) ?? string.Empty; - - return SupportedSubtitleExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); - } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs index 893b16b140..e7e1d1c633 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Sync; using System; using System.Collections.Generic; @@ -16,10 +17,12 @@ namespace MediaBrowser.Server.Implementations.Sync { private readonly SyncManager _syncManager; private readonly IServerApplicationHost _appHost; + private readonly ILogger _logger; - public SyncedMediaSourceProvider(ISyncManager syncManager, IServerApplicationHost appHost) + public SyncedMediaSourceProvider(ISyncManager syncManager, IServerApplicationHost appHost, ILogger logger) { _appHost = appHost; + _logger = logger; _syncManager = (SyncManager)syncManager; } @@ -28,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Sync var jobItemResult = _syncManager.GetJobItems(new SyncJobItemQuery { AddMetadata = false, - Statuses = new SyncJobItemStatus[] { SyncJobItemStatus.Synced }, + Statuses = new[] { SyncJobItemStatus.Synced }, ItemId = item.Id.ToString("N") }); @@ -49,14 +52,17 @@ namespace MediaBrowser.Server.Implementations.Sync if (targetTuple != null) { var syncTarget = targetTuple.Item2; - + var syncProvider = targetTuple.Item1; var dataProvider = _syncManager.GetDataProvider(targetTuple.Item1, syncTarget); var localItems = await dataProvider.GetCachedItems(syncTarget, serverId, item.Id.ToString("N")).ConfigureAwait(false); foreach (var localItem in localItems) { - list.AddRange(localItem.Item.MediaSources); + foreach (var mediaSource in localItem.Item.MediaSources) + { + await TryAddMediaSource(list, localItem, mediaSource, syncProvider, syncTarget, cancellationToken).ConfigureAwait(false); + } } } } @@ -64,5 +70,42 @@ namespace MediaBrowser.Server.Implementations.Sync return list; } + + private async Task TryAddMediaSource(List list, + LocalItem item, + MediaSourceInfo mediaSource, + IServerSyncProvider provider, + SyncTarget target, + CancellationToken cancellationToken) + { + var requiresDynamicAccess = provider as IRequiresDynamicAccess; + + if (requiresDynamicAccess == null) + { + list.Add(mediaSource); + return; + } + + try + { + var dynamicInfo = await requiresDynamicAccess.GetFileInfo(item.LocalPath, target, cancellationToken).ConfigureAwait(false); + + foreach (var stream in mediaSource.MediaStreams) + { + var dynamicStreamInfo = await requiresDynamicAccess.GetFileInfo(stream.ExternalId, target, cancellationToken).ConfigureAwait(false); + + stream.Path = dynamicStreamInfo.Path; + } + + mediaSource.Path = dynamicInfo.Path; + mediaSource.Protocol = dynamicInfo.Protocol; + + list.Add(mediaSource); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting dynamic media source info", ex); + } + } } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index dccef68ed4..84187e72bc 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.600 + 3.0.602 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 b35ce68d6d..59ec2aa65b 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.600 + 3.0.602 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index ea45fdfe19..6f4b6a7e39 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.600 + 3.0.602 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 6fc7e46393..4d919a965e 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.600 + 3.0.602 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 - +