Jelajahi Sumber

fixes #838 - Support rtmp protocol with channels

Luke Pulverenti 11 tahun lalu
induk
melakukan
21fd761b05
27 mengubah file dengan 189 tambahan dan 333 penghapusan
  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>