فهرست منبع

add methods to media source manager

Luke Pulverenti 10 سال پیش
والد
کامیت
75018055b2
34فایلهای تغییر یافته به همراه390 افزوده شده و 264 حذف شده
  1. 15 49
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  2. 1 1
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  3. 5 6
      MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
  4. 1 2
      MediaBrowser.Api/Playback/Hls/MpegDashService.cs
  5. 1 2
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  6. 23 35
      MediaBrowser.Api/Playback/MediaInfoService.cs
  7. 1 1
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  8. 1 3
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  9. 1 2
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  10. 4 3
      MediaBrowser.Api/Subtitles/SubtitleService.cs
  11. 1 53
      MediaBrowser.Controller/Entities/IHasMediaSources.cs
  12. 1 2
      MediaBrowser.Controller/Entities/Video.cs
  13. 46 1
      MediaBrowser.Controller/Library/IMediaSourceManager.cs
  14. 19 0
      MediaBrowser.Controller/Library/IMediaSourceProvider.cs
  15. 1 0
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  16. 3 2
      MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
  17. 5 3
      MediaBrowser.Dlna/Didl/DidlBuilder.cs
  18. 5 6
      MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
  19. 15 16
      MediaBrowser.Dlna/PlayTo/PlayToController.cs
  20. 6 7
      MediaBrowser.Dlna/PlayTo/PlayToManager.cs
  21. 9 41
      MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
  22. 3 0
      MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
  23. 3 0
      MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
  24. 1 0
      MediaBrowser.Model/MediaBrowser.Model.csproj
  25. 10 11
      MediaBrowser.Model/Sync/SyncDialogOptions.cs
  26. 17 0
      MediaBrowser.Model/Sync/SyncQualityOption.cs
  27. 4 2
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  28. 148 2
      MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
  29. 1 0
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  30. 4 2
      MediaBrowser.Server.Implementations/Sync/SyncConvertScheduledTask.cs
  31. 5 3
      MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
  32. 6 4
      MediaBrowser.Server.Implementations/Sync/SyncManager.cs
  33. 17 0
      MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
  34. 7 5
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs

+ 15 - 49
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1,10 +1,9 @@
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Diagnostics;
-using MediaBrowser.Model.Extensions;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -15,6 +14,7 @@ using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.MediaInfo;
 using System;
@@ -69,19 +69,19 @@ namespace MediaBrowser.Api.Playback
         protected ILiveTvManager LiveTvManager { get; private set; }
         protected IDlnaManager DlnaManager { get; private set; }
         protected IDeviceManager DeviceManager { get; private set; }
-        protected IChannelManager ChannelManager { get; private set; }
         protected ISubtitleEncoder SubtitleEncoder { get; private set; }
         protected IProcessManager ProcessManager { get; private set; }
+        protected IMediaSourceManager MediaSourceManager { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
         /// </summary>
-        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager)
+        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager)
         {
+            MediaSourceManager = mediaSourceManager;
             ProcessManager = processManager;
             DeviceManager = deviceManager;
             SubtitleEncoder = subtitleEncoder;
-            ChannelManager = channelManager;
             DlnaManager = dlnaManager;
             LiveTvManager = liveTvManager;
             FileSystem = fileSystem;
@@ -1657,8 +1657,8 @@ namespace MediaBrowser.Api.Playback
 
                 var source = string.IsNullOrEmpty(request.MediaSourceId)
                     ? recording.GetMediaSources(false).First()
-                    : recording.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));
-
+                    : MediaSourceManager.GetStaticMediaSource(recording, request.MediaSourceId, false);
+                
                 mediaStreams = source.MediaStreams;
 
                 // Just to prevent this from being null and causing other methods to fail
@@ -1696,25 +1696,13 @@ namespace MediaBrowser.Api.Playback
                 // Just to prevent this from being null and causing other methods to fail
                 state.MediaPath = string.Empty;
             }
-            else if (item is IChannelMediaItem)
-            {
-                var mediaSource = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
-                state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
-                state.InputProtocol = mediaSource.Protocol;
-                state.MediaPath = mediaSource.Path;
-                state.RunTimeTicks = item.RunTimeTicks;
-                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
-                state.InputBitrate = mediaSource.Bitrate;
-                state.InputFileSize = mediaSource.Size;
-                state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
-                mediaStreams = mediaSource.MediaStreams;
-            }
             else
             {
-                var hasMediaSources = (IHasMediaSources)item;
+                var mediaSources = await MediaSourceManager.GetPlayackMediaSources(request.Id, cancellationToken).ConfigureAwait(false);
+
                 var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
-                    ? hasMediaSources.GetMediaSources(false).First()
-                    : hasMediaSources.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));
+                    ? mediaSources.First()
+                    : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId));
 
                 mediaStreams = mediaSource.MediaStreams;
 
@@ -1724,6 +1712,8 @@ namespace MediaBrowser.Api.Playback
                 state.InputFileSize = mediaSource.Size;
                 state.InputBitrate = mediaSource.Bitrate;
                 state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
+                state.RunTimeTicks = mediaSource.RunTimeTicks;
+                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
 
                 var video = item as Video;
 
@@ -1746,7 +1736,6 @@ namespace MediaBrowser.Api.Playback
                     }
                 }
 
-                state.RunTimeTicks = mediaSource.RunTimeTicks;
             }
 
             var videoRequest = request as VideoStreamRequest;
@@ -1869,29 +1858,6 @@ namespace MediaBrowser.Api.Playback
             state.AllMediaStreams = mediaStreams;
         }
 
-        private async Task<MediaSourceInfo> GetChannelMediaInfo(string id,
-            string mediaSourceId,
-            CancellationToken cancellationToken)
-        {
-            var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, true, cancellationToken)
-                .ConfigureAwait(false);
-
-            var list = channelMediaSources.ToList();
-
-            if (!string.IsNullOrWhiteSpace(mediaSourceId))
-            {
-                var source = list
-                    .FirstOrDefault(i => string.Equals(mediaSourceId, i.Id));
-
-                if (source != null)
-                {
-                    return source;
-                }
-            }
-
-            return list.First();
-        }
-
         private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
         {
             if (videoStream.IsInterlaced)

+ 1 - 1
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -24,7 +24,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public abstract class BaseHlsService : BaseStreamingService
     {
-        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
+        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager)
         {
         }
 

+ 5 - 6
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -1,10 +1,8 @@
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Diagnostics;
-using MediaBrowser.Model.Extensions;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
@@ -12,6 +10,7 @@ using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using ServiceStack;
 using System;
@@ -64,7 +63,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class DynamicHlsService : BaseHlsService
     {
-        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
+        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager)
         {
             NetworkManager = networkManager;
         }

+ 1 - 2
MediaBrowser.Api/Playback/Hls/MpegDashService.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
 using MediaBrowser.Controller.Diagnostics;
@@ -52,7 +51,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class MpegDashService : BaseHlsService
     {
-        public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
+        public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager)
         {
             NetworkManager = networkManager;
         }

+ 1 - 2
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
 using MediaBrowser.Controller.Diagnostics;
@@ -58,7 +57,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public class VideoHlsService : BaseHlsService
     {
-        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
+        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager)
         {
         }
 

+ 23 - 35
MediaBrowser.Api/Playback/MediaInfoService.cs

@@ -1,18 +1,13 @@
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.MediaInfo;
 using ServiceStack;
-using System.Collections.Generic;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.Playback
 {
-    [Route("/Items/{Id}/MediaInfo", "GET", Summary = "Gets live playback media info for an item")]
     [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")]
     public class GetLiveMediaInfo : IReturn<LiveMediaInfoResult>
     {
@@ -23,46 +18,39 @@ namespace MediaBrowser.Api.Playback
         public string UserId { get; set; }
     }
 
+    [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")]
+    public class GetPlaybackInfo : IReturn<LiveMediaInfoResult>
+    {
+        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+        public string Id { get; set; }
+
+        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string UserId { get; set; }
+    }
+
     [Authenticated]
     public class MediaInfoService : BaseApiService
     {
-        private readonly ILibraryManager _libraryManager;
-        private readonly IChannelManager _channelManager;
-        private readonly IUserManager _userManager;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
-        public MediaInfoService(ILibraryManager libraryManager, IChannelManager channelManager, IUserManager userManager)
+        public MediaInfoService(IMediaSourceManager mediaSourceManager)
         {
-            _libraryManager = libraryManager;
-            _channelManager = channelManager;
-            _userManager = userManager;
+            _mediaSourceManager = mediaSourceManager;
         }
 
-        public async Task<object> Get(GetLiveMediaInfo request)
+        public async Task<object> Get(GetPlaybackInfo request)
         {
-            var item = _libraryManager.GetItemById(request.Id);
-            IEnumerable<MediaSourceInfo> mediaSources;
-
-            var channelItem = item as IChannelMediaItem;
-            var user = _userManager.GetUserById(request.UserId);
+            var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.Id, request.UserId, CancellationToken.None).ConfigureAwait(false);
 
-            if (channelItem != null)
-            {
-                mediaSources = await _channelManager.GetChannelItemMediaSources(request.Id, true, CancellationToken.None)
-                        .ConfigureAwait(false);
-            }
-            else
+            return ToOptimizedResult(new LiveMediaInfoResult
             {
-                var hasMediaSources = (IHasMediaSources)item;
+                MediaSources = mediaSources.ToList()
+            });
+        }
 
-                if (user == null)
-                {
-                    mediaSources = hasMediaSources.GetMediaSources(true);
-                }
-                else
-                {
-                    mediaSources = hasMediaSources.GetMediaSources(true, user);
-                }
-            }
+        public async Task<object> Get(GetLiveMediaInfo request)
+        {
+            var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.Id, request.UserId, CancellationToken.None).ConfigureAwait(false);
 
             return ToOptimizedResult(new LiveMediaInfoResult
             {

+ 1 - 1
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class AudioService : BaseProgressiveStreamingService
     {
-        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager, imageProcessor, httpClient)
+        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager, imageProcessor, httpClient)
         {
         }
 

+ 1 - 3
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
 using MediaBrowser.Controller.Diagnostics;
@@ -16,7 +15,6 @@ using ServiceStack.Web;
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -30,7 +28,7 @@ namespace MediaBrowser.Api.Playback.Progressive
         protected readonly IImageProcessor ImageProcessor;
         protected readonly IHttpClient HttpClient;
 
-        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
+        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager)
         {
             ImageProcessor = imageProcessor;
             HttpClient = httpClient;

+ 1 - 2
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
 using MediaBrowser.Controller.Diagnostics;
@@ -64,7 +63,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class VideoService : BaseProgressiveStreamingService
     {
-        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager, imageProcessor, httpClient)
+        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IMediaSourceManager mediaSourceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, subtitleEncoder, deviceManager, processManager, mediaSourceManager, imageProcessor, httpClient)
         {
         }
 

+ 4 - 3
MediaBrowser.Api/Subtitles/SubtitleService.cs

@@ -124,20 +124,21 @@ namespace MediaBrowser.Api.Subtitles
         private readonly ILibraryManager _libraryManager;
         private readonly ISubtitleManager _subtitleManager;
         private readonly ISubtitleEncoder _subtitleEncoder;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
-        public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder)
+        public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager)
         {
             _libraryManager = libraryManager;
             _subtitleManager = subtitleManager;
             _subtitleEncoder = subtitleEncoder;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         public object Get(GetSubtitlePlaylist request)
         {
             var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
 
-            var mediaSource = item.GetMediaSources(false)
-                .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id));
+            var mediaSource = _mediaSourceManager.GetStaticMediaSource(item, request.MediaSourceId, false);
 
             var builder = new StringBuilder();
 

+ 1 - 53
MediaBrowser.Controller/Entities/IHasMediaSources.cs

@@ -1,9 +1,6 @@
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 
 namespace MediaBrowser.Controller.Entities
 {
@@ -22,53 +19,4 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
         IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
     }
-
-    public static class HasMediaSourceExtensions
-    {
-        public static IEnumerable<MediaSourceInfo> GetMediaSources(this IHasMediaSources item, bool enablePathSubstitution, User user)
-        {
-            if (item == null)
-            {
-                throw new ArgumentNullException("item");
-            }
-
-            if (!(item is Video))
-            {
-                return item.GetMediaSources(enablePathSubstitution);
-            }
-
-            if (user == null)
-            {
-                throw new ArgumentNullException("user");
-            }
-
-            var sources = item.GetMediaSources(enablePathSubstitution).ToList();
-
-            var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference)
-            ? new string[] { }
-            : new[] { user.Configuration.AudioLanguagePreference };
-
-            var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
-                ? new List<string> { }
-                : new List<string> { user.Configuration.SubtitleLanguagePreference };
-
-            foreach (var source in sources)
-            {
-                source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(
-                    source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack);
-
-                var defaultAudioIndex = source.DefaultAudioStreamIndex;
-                var audioLangage = defaultAudioIndex == null
-                    ? null
-                    : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault();
-
-                source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams,
-                    preferredSubs,
-                    user.Configuration.SubtitleMode,
-                    audioLangage);
-            }
-
-            return sources;
-        }
-    }
 }

+ 1 - 2
MediaBrowser.Controller/Entities/Video.cs

@@ -460,7 +460,7 @@ namespace MediaBrowser.Controller.Entities
 
             return result.OrderBy(i =>
             {
-                if (item.VideoType == VideoType.VideoFile)
+                if (i.VideoType == VideoType.VideoFile)
                 {
                     return 0;
                 }
@@ -556,7 +556,6 @@ namespace MediaBrowser.Controller.Entities
             return info;
         }
 
-
         private static string GetMediaSourceName(Video video, List<MediaStream> mediaStreams)
         {
             var terms = new List<string>();

+ 46 - 1
MediaBrowser.Controller/Library/IMediaSourceManager.cs

@@ -1,12 +1,22 @@
-using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Controller.Library
 {
     public interface IMediaSourceManager
     {
+        /// <summary>
+        /// Adds the parts.
+        /// </summary>
+        /// <param name="providers">The providers.</param>
+        void AddParts(IEnumerable<IMediaSourceProvider> providers);
+
         /// <summary>
         /// Gets the media streams.
         /// </summary>
@@ -25,5 +35,40 @@ namespace MediaBrowser.Controller.Library
         /// <param name="query">The query.</param>
         /// <returns>IEnumerable&lt;MediaStream&gt;.</returns>
         IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query);
+
+        /// <summary>
+        /// Gets the playack media sources.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="userId">The user identifier.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
+        Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Gets the playack media sources.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task&lt;IEnumerable&lt;MediaSourceInfo&gt;&gt;.</returns>
+        Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Gets the static media sources.
+        /// </summary>
+        /// <param name="item">The item.</param>
+        /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
+        /// <param name="user">The user.</param>
+        /// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
+        IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user);
+
+        /// <summary>
+        /// Gets the static media source.
+        /// </summary>
+        /// <param name="item">The item.</param>
+        /// <param name="mediaSourceId">The media source identifier.</param>
+        /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
+        /// <returns>MediaSourceInfo.</returns>
+        MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
     }
 }

+ 19 - 0
MediaBrowser.Controller/Library/IMediaSourceProvider.cs

@@ -0,0 +1,19 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Library
+{
+    public interface IMediaSourceProvider
+    {
+        /// <summary>
+        /// Gets the media sources.
+        /// </summary>
+        /// <param name="item">The item.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task&lt;IEnumerable&lt;MediaSourceInfo&gt;&gt;.</returns>
+        Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken);
+    }
+}

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -172,6 +172,7 @@
     <Compile Include="Library\DeleteOptions.cs" />
     <Compile Include="Library\ILibraryPostScanTask.cs" />
     <Compile Include="Library\IMediaSourceManager.cs" />
+    <Compile Include="Library\IMediaSourceProvider.cs" />
     <Compile Include="Library\IMetadataFileSaver.cs" />
     <Compile Include="Library\IMetadataSaver.cs" />
     <Compile Include="Library\IMusicManager.cs" />

+ 3 - 2
MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs

@@ -32,7 +32,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
         private readonly ILibraryManager _libraryManager;
         private readonly IChannelManager _channelManager;
         private readonly IUserDataManager _userDataManager;
-        private IServerConfigurationManager _config;
+        private readonly IServerConfigurationManager _config;
         private readonly User _user;
 
         private const string NS_DC = "http://purl.org/dc/elements/1.1/";
@@ -46,6 +46,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
         private readonly DidlBuilder _didlBuilder;
 
         private readonly DeviceProfile _profile;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
         public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager)
             : base(config, logger)
@@ -58,7 +59,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
             _profile = profile;
             _config = config;
 
-            _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization);
+            _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, _mediaSourceManager);
         }
 
         protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)

+ 5 - 3
MediaBrowser.Dlna/Didl/DidlBuilder.cs

@@ -37,14 +37,16 @@ namespace MediaBrowser.Dlna.Didl
         private readonly User _user;
         private readonly IUserDataManager _userDataManager;
         private readonly ILocalizationManager _localization;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
-        public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization)
+        public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
         {
             _profile = profile;
             _imageProcessor = imageProcessor;
             _serverAddress = serverAddress;
             _userDataManager = userDataManager;
             _localization = localization;
+            _mediaSourceManager = mediaSourceManager;
             _accessToken = accessToken;
             _user = user;
         }
@@ -122,7 +124,7 @@ namespace MediaBrowser.Dlna.Didl
         {
             if (streamInfo == null)
             {
-                var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();
+                var sources = _user == null ? video.GetMediaSources(true).ToList() : _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
 
                 streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
                 {
@@ -342,7 +344,7 @@ namespace MediaBrowser.Dlna.Didl
 
             if (streamInfo == null)
             {
-                var sources = _user == null ? audio.GetMediaSources(true).ToList() : audio.GetMediaSources(true, _user).ToList();
+                var sources = _user == null ? audio.GetMediaSources(true).ToList() : _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
 
                 streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
                {

+ 5 - 6
MediaBrowser.Dlna/Main/DlnaEntryPoint.cs

@@ -7,7 +7,6 @@ using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
-using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Dlna.Channels;
@@ -30,13 +29,13 @@ namespace MediaBrowser.Dlna.Main
         private PlayToManager _manager;
         private readonly ISessionManager _sessionManager;
         private readonly IHttpClient _httpClient;
-        private readonly IItemRepository _itemRepo;
         private readonly ILibraryManager _libraryManager;
         private readonly IUserManager _userManager;
         private readonly IDlnaManager _dlnaManager;
         private readonly IImageProcessor _imageProcessor;
         private readonly IUserDataManager _userDataManager;
         private readonly ILocalizationManager _localization;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
         private SsdpHandler _ssdpHandler;
         private DeviceDiscovery _deviceDiscovery;
@@ -44,20 +43,20 @@ namespace MediaBrowser.Dlna.Main
         private readonly List<string> _registeredServerIds = new List<string>();
         private bool _dlnaServerStarted;
 
-        public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor, IUserDataManager userDataManager, ILocalizationManager localization)
+        public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
         {
             _config = config;
             _appHost = appHost;
             _network = network;
             _sessionManager = sessionManager;
             _httpClient = httpClient;
-            _itemRepo = itemRepo;
             _libraryManager = libraryManager;
             _userManager = userManager;
             _dlnaManager = dlnaManager;
             _imageProcessor = imageProcessor;
             _userDataManager = userDataManager;
             _localization = localization;
+            _mediaSourceManager = mediaSourceManager;
             _logger = logManager.GetLogger("Dlna");
         }
 
@@ -217,7 +216,6 @@ namespace MediaBrowser.Dlna.Main
                 {
                     _manager = new PlayToManager(_logger,
                         _sessionManager,
-                        _itemRepo,
                         _libraryManager,
                         _userManager,
                         _dlnaManager,
@@ -227,7 +225,8 @@ namespace MediaBrowser.Dlna.Main
                         _httpClient,
                         _config,
                         _userDataManager,
-                        _localization);
+                        _localization,
+                        _mediaSourceManager);
 
                     _manager.Start();
                 }

+ 15 - 16
MediaBrowser.Dlna/PlayTo/PlayToController.cs

@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
-using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Dlna.Didl;
 using MediaBrowser.Dlna.Ssdp;
@@ -27,7 +26,6 @@ namespace MediaBrowser.Dlna.PlayTo
         private Device _device;
         private readonly SessionInfo _session;
         private readonly ISessionManager _sessionManager;
-        private readonly IItemRepository _itemRepository;
         private readonly ILibraryManager _libraryManager;
         private readonly ILogger _logger;
         private readonly IDlnaManager _dlnaManager;
@@ -35,6 +33,7 @@ namespace MediaBrowser.Dlna.PlayTo
         private readonly IImageProcessor _imageProcessor;
         private readonly IUserDataManager _userDataManager;
         private readonly ILocalizationManager _localization;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
         private readonly DeviceDiscovery _deviceDiscovery;
         private readonly string _serverAddress;
@@ -55,10 +54,9 @@ namespace MediaBrowser.Dlna.PlayTo
 
         private Timer _updateTimer;
 
-        public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, DeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization)
+        public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, DeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
         {
             _session = session;
-            _itemRepository = itemRepository;
             _sessionManager = sessionManager;
             _libraryManager = libraryManager;
             _dlnaManager = dlnaManager;
@@ -68,6 +66,7 @@ namespace MediaBrowser.Dlna.PlayTo
             _deviceDiscovery = deviceDiscovery;
             _userDataManager = userDataManager;
             _localization = localization;
+            _mediaSourceManager = mediaSourceManager;
             _accessToken = accessToken;
             _logger = logger;
         }
@@ -140,7 +139,7 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             try
             {
-                var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager);
+                var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager);
                 if (streamInfo.Item != null)
                 {
                     var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
@@ -150,7 +149,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
                 }
 
-                streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager);
+                streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
                 if (streamInfo.Item == null) return;
                 
                 var newItemProgress = GetProgressInfo(e.NewMediaInfo, streamInfo);
@@ -167,7 +166,7 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             try
             {
-                var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+                var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager);
 
                 if (streamInfo.Item == null) return;
 
@@ -229,7 +228,7 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             try
             {
-                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager);
 
                 if (info.Item != null)
                 {
@@ -248,7 +247,7 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             try
             {
-                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager);
 
                 if (info.Item != null)
                 {
@@ -376,7 +375,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (media != null)
             {
-                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
+                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager, _mediaSourceManager);
 
                 if (info.Item != null && !info.IsDirectStream)
                 {
@@ -472,7 +471,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             var hasMediaSources = item as IHasMediaSources;
             var mediaSources = hasMediaSources != null
-                ? (user == null ? hasMediaSources.GetMediaSources(true) : hasMediaSources.GetMediaSources(true, user)).ToList()
+                ? (user == null ? hasMediaSources.GetMediaSources(true) : _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
                 : new List<MediaSourceInfo>();
 
             var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
@@ -480,7 +479,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             playlistItem.StreamUrl = playlistItem.StreamInfo.ToUrl(_serverAddress, _accessToken);
 
-            var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization)
+            var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager)
                 .GetItemDidl(item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
 
             playlistItem.Didl = itemXml;
@@ -737,7 +736,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (media != null)
             {
-                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
+                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager, _mediaSourceManager);
 
                 if (info.Item != null)
                 {
@@ -763,7 +762,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (media != null)
             {
-                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
+                var info = StreamParams.ParseFromUrl(media.Url, _libraryManager, _mediaSourceManager);
 
                 if (info.Item != null)
                 {
@@ -824,7 +823,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 return null;
             }
 
-            public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager)
+            public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager)
             {
                 var request = new StreamParams
                 {
@@ -892,7 +891,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
                 request.MediaSource = hasMediaSources == null ?
                     null :
-                    hasMediaSources.GetMediaSources(false).FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase));
+                    mediaSourceManager.GetStaticMediaSource(hasMediaSources, request.MediaSourceId, false);
 
 
 

+ 6 - 7
MediaBrowser.Dlna/PlayTo/PlayToManager.cs

@@ -5,7 +5,6 @@ using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
-using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Dlna.Ssdp;
 using MediaBrowser.Model.Logging;
@@ -22,7 +21,6 @@ namespace MediaBrowser.Dlna.PlayTo
         private readonly ILogger _logger;
         private readonly ISessionManager _sessionManager;
 
-        private readonly IItemRepository _itemRepository;
         private readonly ILibraryManager _libraryManager;
         private readonly IUserManager _userManager;
         private readonly IDlnaManager _dlnaManager;
@@ -34,12 +32,12 @@ namespace MediaBrowser.Dlna.PlayTo
         private readonly ILocalizationManager _localization;
 
         private readonly DeviceDiscovery _deviceDiscovery;
-        
-        public PlayToManager(ILogger logger, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization)
+        private readonly IMediaSourceManager _mediaSourceManager;
+
+        public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
         {
             _logger = logger;
             _sessionManager = sessionManager;
-            _itemRepository = itemRepository;
             _libraryManager = libraryManager;
             _userManager = userManager;
             _dlnaManager = dlnaManager;
@@ -50,6 +48,7 @@ namespace MediaBrowser.Dlna.PlayTo
             _config = config;
             _userDataManager = userDataManager;
             _localization = localization;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         public void Start()
@@ -102,7 +101,6 @@ namespace MediaBrowser.Dlna.PlayTo
 
                         sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
                             _sessionManager,
-                            _itemRepository,
                             _libraryManager,
                             _logger,
                             _dlnaManager,
@@ -112,7 +110,8 @@ namespace MediaBrowser.Dlna.PlayTo
                             accessToken,
                             _deviceDiscovery,
                             _userDataManager,
-                            _localization);
+                            _localization,
+                            _mediaSourceManager);
 
                         controller.Init(device);
 

+ 9 - 41
MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs

@@ -23,6 +23,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
         private readonly ILiveTvManager _liveTvManager;
         private readonly ILibraryManager _libraryManager;
         private readonly IChannelManager _channelManager;
+        private IMediaSourceManager _mediaSourceManager;
 
         protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
         
@@ -71,10 +72,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
                 var path = recording.RecordingInfo.Path;
                 var mediaUrl = recording.RecordingInfo.Url;
-
+                
                 var source = string.IsNullOrEmpty(request.MediaSourceId)
                     ? recording.GetMediaSources(false).First()
-                    : recording.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));
+                    : _mediaSourceManager.GetStaticMediaSource(recording, request.MediaSourceId, false);
 
                 mediaStreams = source.MediaStreams;
 
@@ -113,25 +114,13 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 // Just to prevent this from being null and causing other methods to fail
                 state.MediaPath = string.Empty;
             }
-            else if (item is IChannelMediaItem)
-            {
-                var mediaSource = await GetChannelMediaInfo(request.ItemId, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
-                state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
-                state.InputProtocol = mediaSource.Protocol;
-                state.MediaPath = mediaSource.Path;
-                state.RunTimeTicks = item.RunTimeTicks;
-                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
-                state.InputBitrate = mediaSource.Bitrate;
-                state.InputFileSize = mediaSource.Size;
-                state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
-                mediaStreams = mediaSource.MediaStreams;
-            }
             else
             {
-                var hasMediaSources = (IHasMediaSources)item;
+                var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, cancellationToken).ConfigureAwait(false);
+
                 var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
-                    ? hasMediaSources.GetMediaSources(false).First()
-                    : hasMediaSources.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));
+                    ? mediaSources.First()
+                    : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId));
 
                 mediaStreams = mediaSource.MediaStreams;
 
@@ -141,6 +130,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 state.InputFileSize = mediaSource.Size;
                 state.InputBitrate = mediaSource.Bitrate;
                 state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
+                state.RunTimeTicks = mediaSource.RunTimeTicks;
+                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
 
                 var video = item as Video;
 
@@ -424,29 +415,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
             return bitrate;
         }
 
-        private async Task<MediaSourceInfo> GetChannelMediaInfo(string id,
-            string mediaSourceId,
-            CancellationToken cancellationToken)
-        {
-            var channelMediaSources = await _channelManager.GetChannelItemMediaSources(id, true, cancellationToken)
-                .ConfigureAwait(false);
-
-            var list = channelMediaSources.ToList();
-
-            if (!string.IsNullOrWhiteSpace(mediaSourceId))
-            {
-                var source = list
-                    .FirstOrDefault(i => string.Equals(mediaSourceId, i.Id));
-
-                if (source != null)
-                {
-                    return source;
-                }
-            }
-
-            return list.First();
-        }
-
         protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls)
         {
             var bitrate = state.OutputVideoBitrate;

+ 3 - 0
MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj

@@ -1124,6 +1124,9 @@
     <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs">
       <Link>Sync\SyncQuality.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Sync\SyncQualityOption.cs">
+      <Link>Sync\SyncQualityOption.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs">
       <Link>Sync\SyncTarget.cs</Link>
     </Compile>

+ 3 - 0
MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj

@@ -1083,6 +1083,9 @@
     <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs">
       <Link>Sync\SyncQuality.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Sync\SyncQualityOption.cs">
+      <Link>Sync\SyncQualityOption.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs">
       <Link>Sync\SyncTarget.cs</Link>
     </Compile>

+ 1 - 0
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -395,6 +395,7 @@
     <Compile Include="Sync\SyncOptions.cs" />
     <Compile Include="Sync\SyncParameter.cs" />
     <Compile Include="Sync\SyncQuality.cs" />
+    <Compile Include="Sync\SyncQualityOption.cs" />
     <Compile Include="Sync\SyncTarget.cs" />
     <Compile Include="System\LogFile.cs" />
     <Compile Include="System\PublicSystemInfo.cs" />

+ 10 - 11
MediaBrowser.Model/Sync/SyncDialogOptions.cs

@@ -1,5 +1,4 @@
 using System.Collections.Generic;
-using MediaBrowser.Model.Dto;
 
 namespace MediaBrowser.Model.Sync
 {
@@ -19,33 +18,33 @@ namespace MediaBrowser.Model.Sync
         /// Gets or sets the quality options.
         /// </summary>
         /// <value>The quality options.</value>
-        public List<NameValuePair> QualityOptions { get; set; }
+        public List<SyncQualityOption> QualityOptions { get; set; }
         
         public SyncDialogOptions()
         {
             Targets = new List<SyncTarget>();
             Options = new List<SyncJobOption>();
-            QualityOptions = new List<NameValuePair>
+            QualityOptions = new List<SyncQualityOption>
             {
-                new NameValuePair
+                new SyncQualityOption
                 {
                     Name = SyncQuality.Original.ToString(),
-                    Value = SyncQuality.Original.ToString()
+                    Id = SyncQuality.Original.ToString()
                 },
-                new NameValuePair
+                new SyncQualityOption
                 {
                     Name = SyncQuality.High.ToString(),
-                    Value = SyncQuality.High.ToString()
+                    Id = SyncQuality.High.ToString()
                 },
-                new NameValuePair
+                new SyncQualityOption
                 {
                     Name = SyncQuality.Medium.ToString(),
-                    Value = SyncQuality.Medium.ToString()
+                    Id = SyncQuality.Medium.ToString()
                 },
-                new NameValuePair
+                new SyncQualityOption
                 {
                     Name = SyncQuality.Low.ToString(),
-                    Value = SyncQuality.Low.ToString()
+                    Id = SyncQuality.Low.ToString()
                 }
             };
         }

+ 17 - 0
MediaBrowser.Model/Sync/SyncQualityOption.cs

@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Model.Sync
+{
+    public class SyncQualityOption
+    {
+        /// <summary>
+        /// Gets or sets the name.
+        /// </summary>
+        /// <value>The name.</value>
+        public string Name { get; set; }
+        /// <summary>
+        /// Gets or sets the identifier.
+        /// </summary>
+        /// <value>The identifier.</value>
+        public string Id { get; set; }
+    }
+}

+ 4 - 2
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -45,8 +45,9 @@ namespace MediaBrowser.Server.Implementations.Dto
         private readonly ISyncManager _syncManager;
         private readonly IApplicationHost _appHost;
         private readonly Func<IDeviceManager> _deviceManager;
+        private readonly Func<IMediaSourceManager> _mediaSourceManager;
 
-        public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost, Func<IDeviceManager> deviceManager)
+        public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost, Func<IDeviceManager> deviceManager, Func<IMediaSourceManager> mediaSourceManager)
         {
             _logger = logger;
             _libraryManager = libraryManager;
@@ -60,6 +61,7 @@ namespace MediaBrowser.Server.Implementations.Dto
             _syncManager = syncManager;
             _appHost = appHost;
             _deviceManager = deviceManager;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         /// <summary>
@@ -257,7 +259,7 @@ namespace MediaBrowser.Server.Implementations.Dto
                     }
                     else
                     {
-                        dto.MediaSources = hasMediaSources.GetMediaSources(true, user).ToList();
+                        dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user).ToList();
                     }
                 }
             }

+ 148 - 2
MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs

@@ -1,19 +1,38 @@
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Server.Implementations.Library
 {
     public class MediaSourceManager : IMediaSourceManager
     {
         private readonly IItemRepository _itemRepo;
+        private readonly IUserManager _userManager;
+        private readonly ILibraryManager _libraryManager;
+        private readonly IChannelManager _channelManager;
 
-        public MediaSourceManager(IItemRepository itemRepo)
+        private IMediaSourceProvider[] _providers;
+
+        public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, IChannelManager channelManager)
         {
             _itemRepo = itemRepo;
+            _userManager = userManager;
+            _libraryManager = libraryManager;
+            _channelManager = channelManager;
+        }
+
+        public void AddParts(IEnumerable<IMediaSourceProvider> providers)
+        {
+            _providers = providers.ToArray();
         }
 
         public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
@@ -102,5 +121,132 @@ namespace MediaBrowser.Server.Implementations.Library
 
             return list;
         }
+
+        public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, CancellationToken cancellationToken)
+        {
+            var item = _libraryManager.GetItemById(id);
+            IEnumerable<MediaSourceInfo> mediaSources;
+
+            var channelItem = item as IChannelMediaItem;
+
+            if (channelItem != null)
+            {
+                mediaSources = await _channelManager.GetChannelItemMediaSources(id, true, cancellationToken)
+                        .ConfigureAwait(false);
+            }
+            else
+            {
+                var hasMediaSources = (IHasMediaSources)item;
+
+                if (string.IsNullOrWhiteSpace(userId))
+                {
+                    mediaSources = hasMediaSources.GetMediaSources(true);
+                }
+                else
+                {
+                    var user = _userManager.GetUserById(userId);
+                    mediaSources = GetStaticMediaSources(hasMediaSources, true, user);
+                }
+            }
+
+            return mediaSources;
+        }
+
+        public Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, CancellationToken cancellationToken)
+        {
+            return GetPlayackMediaSources(id, null, cancellationToken);
+        }
+
+        public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution)
+        {
+            if (item == null)
+            {
+                throw new ArgumentNullException("item");
+            }
+
+            if (!(item is Video))
+            {
+                return item.GetMediaSources(enablePathSubstitution);
+            }
+
+            return item.GetMediaSources(enablePathSubstitution);
+        }
+
+        public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user)
+        {
+            if (item == null)
+            {
+                throw new ArgumentNullException("item");
+            }
+
+            if (!(item is Video))
+            {
+                return item.GetMediaSources(enablePathSubstitution);
+            }
+
+            if (user == null)
+            {
+                throw new ArgumentNullException("user");
+            }
+
+            var sources = item.GetMediaSources(enablePathSubstitution).ToList();
+
+            foreach (var source in sources)
+            {
+                SetUserProperties(source, user);
+            }
+
+            return sources;
+        }
+
+        private void SetUserProperties(MediaSourceInfo source, User user)
+        {
+            var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference)
+            ? new string[] { }
+            : new[] { user.Configuration.AudioLanguagePreference };
+
+            var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
+                ? new List<string> { }
+                : new List<string> { user.Configuration.SubtitleLanguagePreference };
+
+            source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack);
+
+            var defaultAudioIndex = source.DefaultAudioStreamIndex;
+            var audioLangage = defaultAudioIndex == null
+                ? null
+                : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault();
+
+            source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams,
+                preferredSubs,
+                user.Configuration.SubtitleMode,
+                audioLangage);
+        }
+
+        private IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
+        {
+            return sources.OrderBy(i =>
+            {
+                if (i.VideoType.HasValue && i.VideoType.Value == VideoType.VideoFile)
+                {
+                    return 0;
+                }
+
+                return 1;
+
+            }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
+            .ThenByDescending(i =>
+            {
+                var stream = i.VideoStream;
+
+                return stream == null || stream.Width == null ? 0 : stream.Width.Value;
+            })
+            .ToList();
+        }
+
+
+        public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
+        {
+            return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
+        }
     }
 }

+ 1 - 0
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -309,6 +309,7 @@
     <Compile Include="Sync\MediaSync.cs" />
     <Compile Include="Sync\MultiProviderSync.cs" />
     <Compile Include="Sync\ServerSyncScheduledTask.cs" />
+    <Compile Include="Sync\SyncedMediaSourceProvider.cs" />
     <Compile Include="Sync\SyncRegistrationInfo.cs" />
     <Compile Include="Sync\SyncConfig.cs" />
     <Compile Include="Sync\SyncJobProcessor.cs" />

+ 4 - 2
MediaBrowser.Server.Implementations/Sync/SyncConvertScheduledTask.cs

@@ -25,8 +25,9 @@ namespace MediaBrowser.Server.Implementations.Sync
         private readonly ISubtitleEncoder _subtitleEncoder;
         private readonly IConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
-        public SyncConvertScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem)
+        public SyncConvertScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager)
         {
             _libraryManager = libraryManager;
             _syncRepo = syncRepo;
@@ -38,6 +39,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             _subtitleEncoder = subtitleEncoder;
             _config = config;
             _fileSystem = fileSystem;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         public string Name
@@ -60,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.Sync
 
         public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
         {
-            return new SyncJobProcessor(_libraryManager, _syncRepo, (SyncManager)_syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem)
+            return new SyncJobProcessor(_libraryManager, _syncRepo, (SyncManager)_syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem, _mediaSourceManager)
                 .Sync(progress, cancellationToken);
         }
 

+ 5 - 3
MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs

@@ -38,8 +38,9 @@ namespace MediaBrowser.Server.Implementations.Sync
         private readonly ISubtitleEncoder _subtitleEncoder;
         private readonly IConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
-        public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, SyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem)
+        public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, SyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager)
         {
             _libraryManager = libraryManager;
             _syncRepo = syncRepo;
@@ -51,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             _subtitleEncoder = subtitleEncoder;
             _config = config;
             _fileSystem = fileSystem;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         public async Task EnsureJobItems(SyncJob job)
@@ -491,7 +493,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             options.Context = EncodingContext.Static;
             options.Profile = profile;
             options.ItemId = item.Id.ToString("N");
-            options.MediaSources = item.GetMediaSources(false, user).ToList();
+            options.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();
 
             var streamInfo = new StreamBuilder().BuildVideoItem(options);
             var mediaSource = streamInfo.MediaSource;
@@ -682,7 +684,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             options.Context = EncodingContext.Static;
             options.Profile = profile;
             options.ItemId = item.Id.ToString("N");
-            options.MediaSources = item.GetMediaSources(false, user).ToList();
+            options.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();
 
             var streamInfo = new StreamBuilder().BuildAudioItem(options);
             var mediaSource = streamInfo.MediaSource;

+ 6 - 4
MediaBrowser.Server.Implementations/Sync/SyncManager.cs

@@ -47,7 +47,8 @@ namespace MediaBrowser.Server.Implementations.Sync
         private readonly IFileSystem _fileSystem;
         private readonly Func<ISubtitleEncoder> _subtitleEncoder;
         private readonly IConfigurationManager _config;
-        private IUserDataManager _userDataManager;
+        private readonly IUserDataManager _userDataManager;
+        private readonly Func<IMediaSourceManager> _mediaSourceManager;
 
         private ISyncProvider[] _providers = { };
 
@@ -57,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Sync
         public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated;
         public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated;
 
-        public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager)
+        public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager)
         {
             _libraryManager = libraryManager;
             _repo = repo;
@@ -72,6 +73,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             _subtitleEncoder = subtitleEncoder;
             _config = config;
             _userDataManager = userDataManager;
+            _mediaSourceManager = mediaSourceManager;
         }
 
         public void AddParts(IEnumerable<ISyncProvider> providers)
@@ -610,7 +612,7 @@ namespace MediaBrowser.Server.Implementations.Sync
 
         private SyncJobProcessor GetSyncJobProcessor()
         {
-            return new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder(), _config, _fileSystem);
+            return new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder(), _config, _fileSystem, _mediaSourceManager());
         }
 
         public SyncJobItem GetJobItem(string id)
@@ -677,7 +679,7 @@ namespace MediaBrowser.Server.Implementations.Sync
             dtoOptions.Fields.Remove(ItemFields.SyncInfo);
 
             syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions);
-
+            
             var mediaSource = syncedItem.Item.MediaSources
                .FirstOrDefault(i => string.Equals(i.Id, jobItem.MediaSourceId));
 

+ 17 - 0
MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs

@@ -0,0 +1,17 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+    public class SyncedMediaSourceProvider : IMediaSourceProvider
+    {
+        public async Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
+        {
+            return new List<MediaSourceInfo>();
+        }
+    }
+}

+ 7 - 5
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -447,10 +447,10 @@ namespace MediaBrowser.Server.Startup.Common
             TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager);
             RegisterSingleInstance(TVSeriesManager);
 
-            SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder, FileSystemManager, () => SubtitleEncoder, ServerConfigurationManager, UserDataManager);
+            SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder, FileSystemManager, () => SubtitleEncoder, ServerConfigurationManager, UserDataManager, () => MediaSourceManager);
             RegisterSingleInstance(SyncManager);
 
-            DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this, () => DeviceManager);
+            DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this, () => DeviceManager, () => MediaSourceManager);
             RegisterSingleInstance(DtoService);
 
             var encryptionManager = new EncryptionManager();
@@ -462,9 +462,6 @@ namespace MediaBrowser.Server.Startup.Common
             DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, Logger, FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager"));
             RegisterSingleInstance(DeviceManager);
 
-            MediaSourceManager = new MediaSourceManager(ItemRepository);
-            RegisterSingleInstance(MediaSourceManager);
-
             SessionManager = new SessionManager(UserDataManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager);
             RegisterSingleInstance(SessionManager);
 
@@ -479,6 +476,9 @@ namespace MediaBrowser.Server.Startup.Common
             ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient);
             RegisterSingleInstance(ChannelManager);
 
+            MediaSourceManager = new MediaSourceManager(ItemRepository, UserManager, LibraryManager, ChannelManager);
+            RegisterSingleInstance(MediaSourceManager);
+
             var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
             RegisterSingleInstance<IAppThemeManager>(appThemeManager);
 
@@ -754,6 +754,8 @@ namespace MediaBrowser.Server.Startup.Common
 
             ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>());
 
+            MediaSourceManager.AddParts(GetExports<IMediaSourceProvider>());
+            
             NotificationManager.AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>());
             SyncManager.AddParts(GetExports<ISyncProvider>());
         }