Browse Source

fixes #838 - Support rtmp protocol with channels

Luke Pulverenti 11 năm trước cách đây
mục cha
commit
21fd761b05
27 tập tin đã thay đổi với 189 bổ sung333 xóa
  1. 23 54
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  2. 15 6
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  3. 2 1
      MediaBrowser.Api/Playback/StreamState.cs
  4. 7 4
      MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
  5. 0 7
      MediaBrowser.Controller/Dto/IDtoService.cs
  6. 2 1
      MediaBrowser.Controller/Entities/Audio/Audio.cs
  7. 1 1
      MediaBrowser.Controller/Entities/Video.cs
  8. 6 1
      MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
  9. 10 31
      MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
  10. 10 83
      MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
  11. 12 36
      MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
  12. 21 19
      MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
  13. 8 15
      MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
  14. 1 2
      MediaBrowser.Model/Dto/MediaSourceInfo.cs
  15. 7 0
      MediaBrowser.Model/MediaInfo/Container.cs
  16. 2 2
      MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
  17. 6 10
      MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
  18. 6 3
      MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
  19. 8 3
      MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
  20. 7 5
      MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
  21. 1 38
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  22. 2 2
      MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
  23. 23 1
      MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
  24. 4 3
      MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
  25. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  26. 1 1
      Nuget/MediaBrowser.Common.nuspec
  27. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 23 - 54
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1,16 +1,12 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
@@ -19,6 +15,7 @@ using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Library;
 using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -639,16 +636,16 @@ namespace MediaBrowser.Api.Playback
         /// <summary>
         /// Gets the probe size argument.
         /// </summary>
-        /// <param name="isVideo">if set to <c>true</c> [is video].</param>
-        /// <param name="videoType">Type of the video.</param>
-        /// <param name="isoType">Type of the iso.</param>
+        /// <param name="state">The state.</param>
         /// <returns>System.String.</returns>
-        private string GetProbeSizeArgument(bool isVideo, VideoType? videoType, IsoType? isoType)
+        private string GetProbeSizeArgument(StreamState state)
         {
-            var type = !isVideo ? MediaEncoderHelpers.GetInputType(null, null) :
-                MediaEncoderHelpers.GetInputType(videoType, isoType);
+            if (state.PlayableStreamFileNames.Count > 0)
+            {
+                return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
+            }
 
-            return MediaEncoder.GetProbeSizeArgument(type);
+            return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol);
         }
 
         /// <summary>
@@ -765,7 +762,7 @@ namespace MediaBrowser.Api.Playback
         /// <returns>System.String.</returns>
         protected string GetInputArgument(StreamState state)
         {
-            var type = state.IsRemote ? InputType.Url : InputType.File;
+            var protocol = state.InputProtocol;
 
             var inputPath = new[] { state.MediaPath };
 
@@ -773,11 +770,11 @@ namespace MediaBrowser.Api.Playback
             {
                 if (!(state.VideoType == VideoType.Iso && state.IsoMount == null))
                 {
-                    inputPath = MediaEncoderHelpers.GetInputArgument(state.MediaPath, state.IsRemote, state.VideoType, state.IsoType, state.IsoMount, state.PlayableStreamFileNames, out type);
+                    inputPath = MediaEncoderHelpers.GetInputArgument(state.MediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames);
                 }
             }
 
-            return MediaEncoder.GetInputArgument(inputPath, type);
+            return MediaEncoder.GetInputArgument(inputPath, protocol);
         }
 
         /// <summary>
@@ -885,7 +882,7 @@ namespace MediaBrowser.Api.Playback
             }
 
             // This is arbitrary, but add a little buffer time when internet streaming
-            if (state.IsRemote)
+            if (state.InputProtocol != MediaProtocol.File)
             {
                 await Task.Delay(3000, cancellationTokenSource.Token).ConfigureAwait(false);
             }
@@ -1063,11 +1060,6 @@ namespace MediaBrowser.Api.Playback
 
             state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent);
 
-            if (string.IsNullOrWhiteSpace(useragent))
-            {
-                useragent = GetUserAgent(state.MediaPath);
-            }
-
             if (!string.IsNullOrWhiteSpace(useragent))
             {
                 return "-user-agent \"" + useragent + "\"";
@@ -1076,26 +1068,6 @@ namespace MediaBrowser.Api.Playback
             return string.Empty;
         }
 
-        /// <summary>
-        /// Gets the user agent.
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <returns>System.String.</returns>
-        protected string GetUserAgent(string path)
-        {
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException("path");
-
-            }
-            if (path.IndexOf("apple.com", StringComparison.OrdinalIgnoreCase) != -1)
-            {
-                return "QuickTime/7.7.4";
-            }
-
-            return string.Empty;
-        }
-
         /// <summary>
         /// Processes the exited.
         /// </summary>
@@ -1388,12 +1360,12 @@ namespace MediaBrowser.Api.Playback
                 if (!string.IsNullOrEmpty(path))
                 {
                     state.MediaPath = path;
-                    state.IsRemote = false;
+                    state.InputProtocol = MediaProtocol.File;
                 }
                 else if (!string.IsNullOrEmpty(mediaUrl))
                 {
                     state.MediaPath = mediaUrl;
-                    state.IsRemote = true;
+                    state.InputProtocol = MediaProtocol.Http;
                 }
 
                 state.RunTimeTicks = recording.RunTimeTicks;
@@ -1425,14 +1397,14 @@ namespace MediaBrowser.Api.Playback
                 if (!string.IsNullOrEmpty(streamInfo.Path))
                 {
                     state.MediaPath = streamInfo.Path;
-                    state.IsRemote = false;
+                    state.InputProtocol = MediaProtocol.File;
 
                     await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
                 }
                 else if (!string.IsNullOrEmpty(streamInfo.Url))
                 {
                     state.MediaPath = streamInfo.Url;
-                    state.IsRemote = true;
+                    state.InputProtocol = MediaProtocol.Http;
                 }
 
                 state.ReadInputAtNativeFramerate = true;
@@ -1445,7 +1417,7 @@ namespace MediaBrowser.Api.Playback
             {
                 var source = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
                 state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
-                state.IsRemote = source.LocationType == LocationType.Remote;
+                state.InputProtocol = source.Protocol;
                 state.MediaPath = source.Path;
                 state.RunTimeTicks = item.RunTimeTicks;
                 state.RemoteHttpHeaders = source.RequiredHttpHeaders;
@@ -1461,7 +1433,7 @@ namespace MediaBrowser.Api.Playback
                 mediaStreams = mediaSource.MediaStreams;
 
                 state.MediaPath = mediaSource.Path;
-                state.IsRemote = mediaSource.LocationType == LocationType.Remote;
+                state.InputProtocol = mediaSource.Protocol;
                 state.InputContainer = mediaSource.Container;
 
                 if (item is Video)
@@ -1921,18 +1893,15 @@ namespace MediaBrowser.Api.Playback
         {
             var inputModifier = string.Empty;
 
-            var probeSize = GetProbeSizeArgument(state.IsInputVideo, state.VideoType, state.IsoType);
+            var probeSize = GetProbeSizeArgument(state);
             inputModifier += " " + probeSize;
             inputModifier = inputModifier.Trim();
 
-            if (state.IsRemote)
-            {
-                var userAgentParam = GetUserAgentParam(state);
+            var userAgentParam = GetUserAgentParam(state);
 
-                if (!string.IsNullOrWhiteSpace(userAgentParam))
-                {
-                    inputModifier += " " + userAgentParam;
-                }
+            if (!string.IsNullOrWhiteSpace(userAgentParam))
+            {
+                inputModifier += " " + userAgentParam;
             }
 
             inputModifier = inputModifier.Trim();

+ 15 - 6
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Model.IO;
+using MediaBrowser.Model.MediaInfo;
 using ServiceStack.Web;
 using System;
 using System.Collections.Generic;
@@ -118,13 +119,13 @@ namespace MediaBrowser.Api.Playback.Progressive
             var responseHeaders = new Dictionary<string, string>();
 
             // Static remote stream
-            if (request.Static && state.IsRemote)
+            if (request.Static && state.InputProtocol == MediaProtocol.Http)
             {
                 AddDlnaHeaders(state, responseHeaders, true);
 
                 try
                 {
-                    return GetStaticRemoteStreamResult(state.MediaPath, responseHeaders, isHeadRequest).Result;
+                    return GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest).Result;
                 }
                 finally
                 {
@@ -132,6 +133,11 @@ namespace MediaBrowser.Api.Playback.Progressive
                 }
             }
 
+            if (request.Static && state.InputProtocol != MediaProtocol.File)
+            {
+                throw new ArgumentException(string.Format("Input protocol {0} cannot be streamed statically.", state.InputProtocol));
+            }
+
             var outputPath = state.OutputFilePath;
             var outputPathExists = File.Exists(outputPath);
 
@@ -186,16 +192,19 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// <summary>
         /// Gets the static remote stream result.
         /// </summary>
-        /// <param name="mediaPath">The media path.</param>
+        /// <param name="state">The state.</param>
         /// <param name="responseHeaders">The response headers.</param>
         /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
         /// <returns>Task{System.Object}.</returns>
-        private async Task<object> GetStaticRemoteStreamResult(string mediaPath, Dictionary<string, string> responseHeaders, bool isHeadRequest)
+        private async Task<object> GetStaticRemoteStreamResult(StreamState state, Dictionary<string, string> responseHeaders, bool isHeadRequest)
         {
+            string useragent = null;
+            state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent);
+
             var options = new HttpRequestOptions
             {
-                Url = mediaPath,
-                UserAgent = GetUserAgent(mediaPath),
+                Url = state.MediaPath,
+                UserAgent = useragent,
                 BufferContent = false
             };
 

+ 2 - 1
MediaBrowser.Api/Playback/StreamState.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
@@ -50,7 +51,7 @@ namespace MediaBrowser.Api.Playback
 
         public string MediaPath { get; set; }
 
-        public bool IsRemote { get; set; }
+        public MediaProtocol InputProtocol { get; set; }
 
         public bool IsInputVideo { get; set; }
 

+ 7 - 4
MediaBrowser.Controller/Channels/ChannelMediaInfo.cs

@@ -1,4 +1,5 @@
-using System;
+using MediaBrowser.Model.MediaInfo;
+using System;
 using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Channels
@@ -20,16 +21,18 @@ namespace MediaBrowser.Controller.Channels
         public int? AudioChannels { get; set; }
         public int? AudioSampleRate { get; set; }
 
-        public bool IsRemote { get; set; }
-
         public string VideoProfile { get; set; }
         public float? VideoLevel { get; set; }
         public float? Framerate { get; set; }
 
+        public MediaProtocol Protocol { get; set; }
+
         public ChannelMediaInfo()
         {
             RequiredHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-            IsRemote = true;
+
+            // This is most common
+            Protocol = MediaProtocol.Http;
         }
     }
 }

+ 0 - 7
MediaBrowser.Controller/Dto/IDtoService.cs

@@ -67,13 +67,6 @@ namespace MediaBrowser.Controller.Dto
         /// <returns>ChapterInfoDto.</returns>
         ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item);
 
-        /// <summary>
-        /// Gets the media sources.
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <returns>List{MediaSourceInfo}.</returns>
-        List<MediaSourceInfo> GetMediaSources(BaseItem item);
-
         /// <summary>
         /// Gets the item by name dto.
         /// </summary>

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

@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -191,7 +192,7 @@ namespace MediaBrowser.Controller.Entities.Audio
             var info = new MediaSourceInfo
             {
                 Id = i.Id.ToString("N"),
-                LocationType = locationType,
+                Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
                 MediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(),
                 Name = i.Name,
                 Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path,

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

@@ -549,7 +549,7 @@ namespace MediaBrowser.Controller.Entities
             {
                 Id = i.Id.ToString("N"),
                 IsoType = i.IsoType,
-                LocationType = locationType,
+                Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
                 MediaStreams = mediaStreams,
                 Name = GetMediaSourceName(i, mediaStreams),
                 Path = enablePathSubstitution ? GetMappedPath(i.Path, locationType) : i.Path,

+ 6 - 1
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -6,7 +6,7 @@ using System.Linq;
 
 namespace MediaBrowser.Controller.LiveTv
 {
-    public class LiveTvChannel : BaseItem, IItemByName
+    public class LiveTvChannel : BaseItem, IItemByName, IHasMediaSources
     {
         /// <summary>
         /// Gets the user data key.
@@ -114,5 +114,10 @@ namespace MediaBrowser.Controller.LiveTv
         {
             return new List<BaseItem>();
         }
+
+        public IEnumerable<Model.Dto.MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
+        {
+            throw new System.NotImplementedException();
+        }
     }
 }

+ 10 - 31
MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
 using System;
 using System.IO;
 using System.Threading;
@@ -35,59 +36,37 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// Extracts the video image.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <param name="threedFormat">The threed format.</param>
         /// <param name="offset">The offset.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{Stream}.</returns>
-        Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+        Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the media info.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, bool isAudio, CancellationToken cancellationToken);
+        Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, MediaProtocol protocol, bool isAudio, CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the probe size argument.
         /// </summary>
-        /// <param name="type">The type.</param>
+        /// <param name="inputFiles">The input files.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <returns>System.String.</returns>
-        string GetProbeSizeArgument(InputType type);
+        string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol);
 
         /// <summary>
         /// Gets the input argument.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <returns>System.String.</returns>
-        string GetInputArgument(string[] inputFiles, InputType type);
-    }
-
-    /// <summary>
-    /// Enum InputType
-    /// </summary>
-    public enum InputType
-    {
-        /// <summary>
-        /// The file
-        /// </summary>
-        File,
-        /// <summary>
-        /// The bluray
-        /// </summary>
-        Bluray,
-        /// <summary>
-        /// The DVD
-        /// </summary>
-        Dvd,
-        /// <summary>
-        /// The URL
-        /// </summary>
-        Url
+        string GetInputArgument(string[] inputFiles, MediaProtocol protocol);
     }
 }

+ 10 - 83
MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
+using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -17,56 +18,22 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// Gets the input argument.
         /// </summary>
         /// <param name="videoPath">The video path.</param>
-        /// <param name="isRemote">if set to <c>true</c> [is remote].</param>
-        /// <param name="videoType">Type of the video.</param>
-        /// <param name="isoType">Type of the iso.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <param name="isoMount">The iso mount.</param>
         /// <param name="playableStreamFileNames">The playable stream file names.</param>
-        /// <param name="type">The type.</param>
         /// <returns>System.String[][].</returns>
-        public static string[] GetInputArgument(string videoPath, bool isRemote, VideoType videoType, IsoType? isoType, IIsoMount isoMount, IEnumerable<string> playableStreamFileNames, out InputType type)
+        public static string[] GetInputArgument(string videoPath, MediaProtocol protocol, IIsoMount isoMount, List<string> playableStreamFileNames)
         {
-            var inputPath = isoMount == null ? new[] { videoPath } : new[] { isoMount.MountedPath };
-
-            type = InputType.File;
-
-            switch (videoType)
+            if (playableStreamFileNames.Count > 0)
             {
-                case VideoType.BluRay:
-                    type = InputType.Bluray;
-                    inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
-                    break;
-                case VideoType.Dvd:
-                    type = InputType.Dvd;
-                    inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
-                    break;
-                case VideoType.Iso:
-                    if (isoType.HasValue)
-                    {
-                        switch (isoType.Value)
-                        {
-                            case IsoType.BluRay:
-                                type = InputType.Bluray;
-                                inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
-                                break;
-                            case IsoType.Dvd:
-                                type = InputType.Dvd;
-                                inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
-                                break;
-                        }
-                    }
-                    break;
-                case VideoType.VideoFile:
-                    {
-                        if (isRemote)
-                        {
-                            type = InputType.Url;
-                        }
-                        break;
-                    }
+                if (isoMount == null)
+                {
+                    return GetPlayableStreamFiles(videoPath, playableStreamFileNames).ToArray();
+                }
+                return GetPlayableStreamFiles(isoMount.MountedPath, playableStreamFileNames).ToArray();
             }
 
-            return inputPath;
+            return new[] {videoPath};
         }
 
         public static List<string> GetPlayableStreamFiles(string rootPath, IEnumerable<string> filenames)
@@ -80,46 +47,6 @@ namespace MediaBrowser.Controller.MediaEncoding
                 .ToList();
         }
 
-        /// <summary>
-        /// Gets the type of the input.
-        /// </summary>
-        /// <param name="videoType">Type of the video.</param>
-        /// <param name="isoType">Type of the iso.</param>
-        /// <returns>InputType.</returns>
-        public static InputType GetInputType(VideoType? videoType, IsoType? isoType)
-        {
-            var type = InputType.File;
-
-            if (videoType.HasValue)
-            {
-                switch (videoType.Value)
-                {
-                    case VideoType.BluRay:
-                        type = InputType.Bluray;
-                        break;
-                    case VideoType.Dvd:
-                        type = InputType.Dvd;
-                        break;
-                    case VideoType.Iso:
-                        if (isoType.HasValue)
-                        {
-                            switch (isoType.Value)
-                            {
-                                case IsoType.BluRay:
-                                    type = InputType.Bluray;
-                                    break;
-                                case IsoType.Dvd:
-                                    type = InputType.Dvd;
-                                    break;
-                            }
-                        }
-                        break;
-                }
-            }
-
-            return type;
-        }
-
         public static MediaInfo GetMediaInfo(InternalMediaInfoResult data)
         {
             var internalStreams = data.streams ?? new MediaStreamInfo[] { };

+ 12 - 36
MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs

@@ -1,22 +1,27 @@
 using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
-using System.Globalization;
 using System.Linq;
 
 namespace MediaBrowser.MediaEncoding.Encoder
 {
     public static class EncodingUtils
     {
-        private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-        
-        public static string GetInputArgument(List<string> inputFiles, bool isRemote)
+        public static string GetInputArgument(List<string> inputFiles, MediaProtocol protocol)
         {
-            if (isRemote)
+            if (protocol == MediaProtocol.Http)
             {
-                return GetHttpInputArgument(inputFiles);
+                var url = inputFiles.First();
+
+                return string.Format("\"{0}\"", url);
+            }
+            if (protocol == MediaProtocol.Rtmp)
+            {
+                var url = inputFiles.First();
+
+                return string.Format("\"{0}\"", url);
             }
 
             return GetConcatInputArgument(inputFiles);
@@ -52,35 +57,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
             return string.Format("file:\"{0}\"", path);
         }
 
-        /// <summary>
-        /// Gets the HTTP input argument.
-        /// </summary>
-        /// <param name="inputFiles">The input files.</param>
-        /// <returns>System.String.</returns>
-        private static string GetHttpInputArgument(IEnumerable<string> inputFiles)
-        {
-            var url = inputFiles.First();
-
-            return string.Format("\"{0}\"", url);
-        }
-
-        private static string GetFastSeekValue(EncodingOptions options)
-        {
-            var time = options.StartTimeTicks;
-
-            if (time.HasValue)
-            {
-                var seconds = TimeSpan.FromTicks(time.Value).TotalSeconds;
-
-                if (seconds > 0)
-                {
-                    return string.Format("-ss {0}", seconds.ToString(UsCulture));
-                }
-            }
-
-            return string.Empty;
-        }
-
         public static string GetProbeSizeArgument(bool isDvd)
         {
             return isDvd ? "-probesize 1G -analyzeduration 200M" : string.Empty;

+ 21 - 19
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.MediaInfo;
 using MediaBrowser.Model.Serialization;
 using System;
 using System.Collections.Concurrent;
@@ -102,37 +103,38 @@ namespace MediaBrowser.MediaEncoding.Encoder
         /// Gets the media info.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, bool isAudio,
+        public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, MediaProtocol protocol, bool isAudio,
             CancellationToken cancellationToken)
         {
-            return GetMediaInfoInternal(GetInputArgument(inputFiles, type), !isAudio,
-                GetProbeSizeArgument(type), cancellationToken);
+            return GetMediaInfoInternal(GetInputArgument(inputFiles, protocol), !isAudio,
+                GetProbeSizeArgument(inputFiles, protocol), cancellationToken);
         }
 
         /// <summary>
         /// Gets the input argument.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <returns>System.String.</returns>
         /// <exception cref="System.ArgumentException">Unrecognized InputType</exception>
-        public string GetInputArgument(string[] inputFiles, InputType type)
+        public string GetInputArgument(string[] inputFiles, MediaProtocol protocol)
         {
-            return EncodingUtils.GetInputArgument(inputFiles.ToList(), type == InputType.Url);
+            return EncodingUtils.GetInputArgument(inputFiles.ToList(), protocol);
         }
 
         /// <summary>
         /// Gets the probe size argument.
         /// </summary>
-        /// <param name="type">The type.</param>
+        /// <param name="inputFiles">The input files.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <returns>System.String.</returns>
-        public string GetProbeSizeArgument(InputType type)
+        public string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol)
         {
-            return EncodingUtils.GetProbeSizeArgument(type == InputType.Dvd);
+            return EncodingUtils.GetProbeSizeArgument(inputFiles.Length > 0);
         }
 
         /// <summary>
@@ -287,27 +289,27 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
         public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
         {
-            return ExtractImage(new[] { path }, InputType.File, true, null, null, cancellationToken);
+            return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
         }
 
-        public Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat,
+        public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat,
             TimeSpan? offset, CancellationToken cancellationToken)
         {
-            return ExtractImage(inputFiles, type, false, threedFormat, offset, cancellationToken);
+            return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken);
         }
 
-        private async Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio,
+        private async Task<Stream> ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio,
             Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
         {
             var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
 
-            var inputArgument = GetInputArgument(inputFiles, type);
+            var inputArgument = GetInputArgument(inputFiles, protocol);
 
             if (!isAudio)
             {
                 try
                 {
-                    return await ExtractImageInternal(inputArgument, type, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
+                    return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
                 }
                 catch
                 {
@@ -315,10 +317,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 }
             }
 
-            return await ExtractImageInternal(inputArgument, type, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
+            return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
         }
 
-        private async Task<Stream> ExtractImageInternal(string inputPath, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+        private async Task<Stream> ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
         {
             if (string.IsNullOrEmpty(inputPath))
             {
@@ -357,7 +359,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) :
                 string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf);
 
-            var probeSize = GetProbeSizeArgument(type);
+            var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol);
 
             if (!string.IsNullOrEmpty(probeSize))
             {

+ 8 - 15
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs

@@ -127,26 +127,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             var subtitleStream = mediaSource.MediaStreams
                 .First(i => i.Type == MediaStreamType.Subtitle && i.Index == subtitleStreamIndex);
 
-            var inputType = mediaSource.LocationType == LocationType.Remote ? InputType.Url : InputType.File;
             var inputFiles = new[] { mediaSource.Path };
 
             if (mediaSource.VideoType.HasValue)
             {
-                if (mediaSource.VideoType.Value == VideoType.BluRay)
+                if (mediaSource.VideoType.Value == VideoType.BluRay ||
+                    mediaSource.VideoType.Value == VideoType.Dvd)
                 {
-                    inputType = InputType.Bluray;
-                    var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSourceId));
-                    inputFiles = mediaSourceItem.GetPlayableStreamFiles().ToArray();
-                }
-                else if (mediaSource.VideoType.Value == VideoType.Dvd)
-                {
-                    inputType = InputType.Dvd;
                     var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSourceId));
                     inputFiles = mediaSourceItem.GetPlayableStreamFiles().ToArray();
                 }
             }
 
-            var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, inputType, subtitleStream, cancellationToken).ConfigureAwait(false);
+            var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false);
 
             var stream = await GetSubtitleStream(fileInfo.Item1, subtitleStream.Language).ConfigureAwait(false);
 
@@ -180,7 +173,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
         private async Task<Tuple<string, string>> GetReadableFile(string mediaPath,
             string[] inputFiles,
-            InputType type,
+            MediaProtocol protocol,
             MediaStream subtitleStream,
             CancellationToken cancellationToken)
         {
@@ -189,7 +182,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 // Extract    
                 var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".ass");
 
-                await ExtractTextSubtitle(inputFiles, type, subtitleStream.Index, false, outputPath, cancellationToken)
+                await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, false, outputPath, cancellationToken)
                         .ConfigureAwait(false);
 
                 return new Tuple<string, string>(outputPath, "ass");
@@ -451,14 +444,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
         /// Extracts the text subtitle.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
-        /// <param name="type">The type.</param>
+        /// <param name="protocol">The protocol.</param>
         /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
         /// <param name="copySubtitleStream">if set to true, copy stream instead of converting.</param>
         /// <param name="outputPath">The output path.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <exception cref="System.ArgumentException">Must use inputPath list overload</exception>
-        private async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex,
+        private async Task ExtractTextSubtitle(string[] inputFiles, MediaProtocol protocol, int subtitleStreamIndex,
             bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
         {
             var semaphore = GetLock(outputPath);
@@ -469,7 +462,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             {
                 if (!File.Exists(outputPath))
                 {
-                    await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, type), subtitleStreamIndex,
+                    await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex,
                             copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false);
                 }
             }

+ 1 - 2
MediaBrowser.Model/Dto/MediaSourceInfo.cs

@@ -8,6 +8,7 @@ namespace MediaBrowser.Model.Dto
 {
     public class MediaSourceInfo
     {
+        public MediaProtocol Protocol { get; set; }
         public string Id { get; set; }
 
         public string Path { get; set; }
@@ -17,8 +18,6 @@ namespace MediaBrowser.Model.Dto
         public string Container { get; set; }
         public long? Size { get; set; }
 
-        public LocationType LocationType { get; set; }
-
         public string Name { get; set; }
 
         public long? RunTimeTicks { get; set; }

+ 7 - 0
MediaBrowser.Model/MediaInfo/Container.cs

@@ -6,4 +6,11 @@ namespace MediaBrowser.Model.MediaInfo
         public const string MP4 = "mp4";
         public const string MKV = "mkv";
     }
+
+    public enum MediaProtocol
+    {
+        File = 0,
+        Http = 1,
+        Rtmp = 2
+    }
 }

+ 2 - 2
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs

@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
 using MediaBrowser.Model.Serialization;
 using System;
 using System.Collections.Generic;
@@ -73,10 +74,9 @@ namespace MediaBrowser.Providers.MediaInfo
             {
             }
 
-            const InputType type = InputType.File;
             var inputPath = new[] { item.Path };
 
-            var result = await _mediaEncoder.GetMediaInfo(inputPath, type, false, cancellationToken).ConfigureAwait(false);
+            var result = await _mediaEncoder.GetMediaInfo(inputPath, MediaProtocol.File, false, cancellationToken).ConfigureAwait(false);
 
             Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
             _json.SerializeToFile(result, cachePath);

+ 6 - 10
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -126,7 +126,7 @@ namespace MediaBrowser.Providers.MediaInfo
 
         private const string SchemaVersion = "1";
 
-        private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item,
+        private async Task<InternalMediaInfoResult> GetMediaInfo(Video item,
             IIsoMount isoMount,
             CancellationToken cancellationToken)
         {
@@ -149,17 +149,13 @@ namespace MediaBrowser.Providers.MediaInfo
             {
             }
 
-            var type = InputType.File;
-            var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath };
+            var protocol = item.LocationType == LocationType.Remote
+                ? MediaProtocol.Http
+                : MediaProtocol.File;
 
-            var video = item as Video;
+            var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames);
 
-            if (video != null)
-            {
-                inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, video.LocationType == LocationType.Remote, video.VideoType, video.IsoType, isoMount, video.PlayableStreamFileNames, out type);
-            }
-
-            var result = await _mediaEncoder.GetMediaInfo(inputPath, type, false, cancellationToken).ConfigureAwait(false);
+            var result = await _mediaEncoder.GetMediaInfo(inputPath, protocol, false, cancellationToken).ConfigureAwait(false);
 
             Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
             _json.SerializeToFile(result, cachePath);

+ 6 - 3
MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs

@@ -9,6 +9,7 @@ using System;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Model.MediaInfo;
 
 namespace MediaBrowser.Providers.MediaInfo
 {
@@ -89,11 +90,13 @@ namespace MediaBrowser.Providers.MediaInfo
                                       ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1))
                                       : TimeSpan.FromSeconds(10);
 
-                InputType type;
+                var protocol = item.LocationType == LocationType.Remote
+                    ? MediaProtocol.Http
+                    : MediaProtocol.File;
 
-                var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, item.LocationType == LocationType.Remote, item.VideoType, item.IsoType, isoMount, item.PlayableStreamFileNames, out type);
+                var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames);
 
-                var stream = await _mediaEncoder.ExtractVideoImage(inputPath, type, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
+                var stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
 
                 return new DynamicImageResponse
                 {

+ 8 - 3
MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs

@@ -8,8 +8,8 @@ using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.MediaInfo;
 using MediaBrowser.Model.Querying;
 using System;
 using System.Collections.Generic;
@@ -182,7 +182,7 @@ namespace MediaBrowser.Server.Implementations.Channels
 
             var list = sources.ToList();
 
-            var cachedVersions = list.Where(i => i.LocationType == LocationType.FileSystem).ToList();
+            var cachedVersions = list.Where(i => i.Protocol == MediaProtocol.File).ToList();
 
             if (cachedVersions.Count > 0)
             {
@@ -190,7 +190,12 @@ namespace MediaBrowser.Server.Implementations.Channels
                 return;
             }
 
-            var source = list.First();
+            var source = list.FirstOrDefault(i => i.Protocol == MediaProtocol.Http);
+
+            if (source == null)
+            {
+                return;
+            }
 
             var options = new HttpRequestOptions
             {

+ 7 - 5
MediaBrowser.Server.Implementations/Channels/ChannelManager.cs

@@ -280,7 +280,7 @@ namespace MediaBrowser.Server.Implementations.Channels
                 MediaStreams = GetMediaStreams(info).ToList(),
 
                 Container = info.Container,
-                LocationType = info.IsRemote ? LocationType.Remote : LocationType.FileSystem,
+                Protocol = info.Protocol,
                 Path = info.Path,
                 RequiredHttpHeaders = info.RequiredHttpHeaders,
                 RunTimeTicks = item.RunTimeTicks,
@@ -555,17 +555,18 @@ namespace MediaBrowser.Server.Implementations.Channels
                 return GetChannelItemEntity(i.Item2, channelProvider, channel, token);
             });
 
-            IEnumerable<BaseItem> internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
+            var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
 
-            internalItems = ApplyFilters(internalItems, query.Filters, user);
+            internalItems = ApplyFilters(internalItems, query.Filters, user).ToArray();
+            await RefreshIfNeeded(internalItems, cancellationToken).ConfigureAwait(false);
 
             if (query.StartIndex.HasValue)
             {
-                internalItems = internalItems.Skip(query.StartIndex.Value);
+                internalItems = internalItems.Skip(query.StartIndex.Value).ToArray();
             }
             if (query.Limit.HasValue)
             {
-                internalItems = internalItems.Take(query.Limit.Value);
+                internalItems = internalItems.Take(query.Limit.Value).ToArray();
             }
 
             var returnItemArray = internalItems.Select(i => _dtoService.GetBaseItemDto(i, query.Fields, user))
@@ -658,6 +659,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             });
 
             var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
+            await RefreshIfNeeded(internalItems, cancellationToken).ConfigureAwait(false);
 
             var returnItemArray = internalItems.Select(i => _dtoService.GetBaseItemDto(i, query.Fields, user))
                 .ToArray();

+ 1 - 38
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -1111,7 +1111,7 @@ namespace MediaBrowser.Server.Implementations.Dto
 
             if (tvChannel != null)
             {
-                dto.MediaSources = GetMediaSources(tvChannel);
+                dto.MediaSources = tvChannel.GetMediaSources(true).ToList();
             }
 
             var channelItem = item as IChannelItem;
@@ -1123,43 +1123,6 @@ namespace MediaBrowser.Server.Implementations.Dto
             }
         }
 
-        public List<MediaSourceInfo> GetMediaSources(BaseItem item)
-        {
-            var video = item as Video;
-
-            if (video != null)
-            {
-                return video.GetMediaSources(true).ToList();
-            }
-
-            var audio = item as Audio;
-
-            if (audio != null)
-            {
-                return audio.GetMediaSources(true).ToList();
-            }
-
-            var result = new List<MediaSourceInfo>
-            {
-                new MediaSourceInfo
-                {
-                    Id = item.Id.ToString("N"),
-                    LocationType = item.LocationType,
-                    Name = item.Name,
-                    Path = GetMappedPath(item),
-                    MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
-                    {
-                        ItemId = item.Id
-
-                    }).ToList(),
-
-                    RunTimeTicks = item.RunTimeTicks
-                }            
-            };
-
-            return result;
-        }
-
         private string GetMappedPath(IHasMetadata item)
         {
             var path = item.Path;

+ 2 - 2
MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs

@@ -222,7 +222,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 RunTimeTicks = (info.EndDate - info.StartDate).Ticks,
                 OriginalAirDate = info.OriginalAirDate,
 
-                MediaSources = _dtoService.GetMediaSources((BaseItem)recording)
+                MediaSources = recording.GetMediaSources(true).ToList()
             };
 
             dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
@@ -317,7 +317,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 Id = info.Id.ToString("N"),
                 MediaType = info.MediaType,
                 ExternalId = info.ExternalId,
-                MediaSources = _dtoService.GetMediaSources(info)
+                MediaSources = info.GetMediaSources(true).ToList()
             };
 
             if (user != null)

+ 23 - 1
MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json

@@ -148,5 +148,27 @@
 	"LabelChapterDownloaders": "Chapter downloaders:",
 	"LabelChapterDownloadersHelp": "Enable and rank your preferred chapter downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
 	"HeaderFavoriteAlbums": "Favorite Albums",
-	"HeaderLatestChannelMedia": "Latest Channel Items"
+	"HeaderLatestChannelMedia": "Latest Channel Items",
+	"ButtonOrganizeFile": "Organize File",
+	"ButtonDeleteFile": "Delete File",
+	"HeaderOrganizeFile": "Organize File",
+	"HeaderDeleteFile": "Delete File",
+	"StatusSkipped": "Skipped",
+	"StatusFailed": "Failed",
+	"StatusSuccess": "Success",
+	"MessageFileWillBeDeleted": "The following file will be deleted:",
+	"MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
+	"MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
+	"MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
+	"MessageDestinationTo": "to:",
+	"HeaderSelectWatchFolder": "Select Watch Folder",
+	"HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
+	"OrganizePatternResult": "Result: {0}",
+	"HeaderRestart": "Restart",
+	"HeaderShutdown": "Shutdown",
+	"MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
+	"MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+	"ButtonUpdateNow": "Update Now",
+	"NewVersionOfSomethingAvailable": "A new version of {0} is available!",
+	"VersionXIsAvailableForDownload": "Version {0} is now available for download."
 }

+ 4 - 3
MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs

@@ -14,6 +14,7 @@ using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Model.MediaInfo;
 
 namespace MediaBrowser.Server.Implementations.MediaEncoder
 {
@@ -133,15 +134,15 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
                         // Add some time for the first chapter to make sure we don't end up with a black image
                         var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);
 
-                        InputType type;
+                        var protocol = MediaProtocol.File;
 
-                        var inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, false, video.VideoType, video.IsoType, null, video.PlayableStreamFileNames, out type);
+                        var inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, protocol, null, video.PlayableStreamFileNames);
 
                         try
                         {
                             Directory.CreateDirectory(Path.GetDirectoryName(path));
 
-                            using (var stream = await _encoder.ExtractVideoImage(inputPath, type, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
+                            using (var stream = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
                             {
                                 using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
                                 {

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.405</version>
+        <version>3.0.406</version>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.405" />
+            <dependency id="MediaBrowser.Common" version="3.0.406" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="SimpleInjector" version="2.5.0" />
             <dependency id="sharpcompress" version="0.10.2" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.405</version>
+        <version>3.0.406</version>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.405</version>
+        <version>3.0.406</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.405" />
+            <dependency id="MediaBrowser.Common" version="3.0.406" />
         </dependencies>
     </metadata>
     <files>