Explorar el Código

live tv stream adjustments, add additional dlna params

Luke Pulverenti hace 11 años
padre
commit
c4f587dd94
Se han modificado 36 ficheros con 204 adiciones y 171 borrados
  1. 1 1
      MediaBrowser.Api/GamesService.cs
  2. 1 1
      MediaBrowser.Api/Movies/MoviesService.cs
  3. 32 12
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  4. 1 1
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  5. 1 1
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  6. 7 3
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  7. 1 1
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  8. 2 0
      MediaBrowser.Api/Playback/StreamRequest.cs
  9. 17 1
      MediaBrowser.Api/Playback/StreamState.cs
  10. 2 2
      MediaBrowser.Controller/Entities/BaseItem.cs
  11. 3 3
      MediaBrowser.Controller/Entities/IHasImages.cs
  12. 80 80
      MediaBrowser.Controller/Library/TVUtils.cs
  13. 12 0
      MediaBrowser.Controller/Net/IHttpResultFactory.cs
  14. 7 23
      MediaBrowser.Controller/Providers/DirectoryService.cs
  15. 1 1
      MediaBrowser.Controller/Providers/ILocalImageProvider.cs
  16. 1 1
      MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs
  17. 1 1
      MediaBrowser.Providers/All/LocalImageProvider.cs
  18. 1 1
      MediaBrowser.Providers/BaseXmlProvider.cs
  19. 1 1
      MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs
  20. 1 1
      MediaBrowser.Providers/Folders/FolderXmlProvider.cs
  21. 1 1
      MediaBrowser.Providers/Games/GameSystemXmlProvider.cs
  22. 1 1
      MediaBrowser.Providers/Games/GameXmlProvider.cs
  23. 1 1
      MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs
  24. 1 1
      MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
  25. 1 1
      MediaBrowser.Providers/Movies/MovieXmlProvider.cs
  26. 1 1
      MediaBrowser.Providers/Movies/TrailerXmlProvider.cs
  27. 1 1
      MediaBrowser.Providers/Music/AlbumXmlProvider.cs
  28. 1 1
      MediaBrowser.Providers/Music/ArtistXmlProvider.cs
  29. 1 1
      MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs
  30. 1 1
      MediaBrowser.Providers/People/PersonXmlProvider.cs
  31. 1 1
      MediaBrowser.Providers/TV/EpisodeXmlProvider.cs
  32. 1 1
      MediaBrowser.Providers/TV/SeasonXmlProvider.cs
  33. 1 1
      MediaBrowser.Providers/TV/SeriesXmlProvider.cs
  34. 5 7
      MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
  35. 13 1
      MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
  36. 0 15
      MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

+ 1 - 1
MediaBrowser.Api/GamesService.cs

@@ -155,7 +155,7 @@ namespace MediaBrowser.Api
 
             var games = items.OfType<Game>().ToList();
 
-            summary.ClientInstalledGameCount = games.Count(i => !i.IsPlaceHolder);
+            summary.ClientInstalledGameCount = games.Count(i => i.IsPlaceHolder);
 
             summary.GameCount = games.Count;
 

+ 1 - 1
MediaBrowser.Api/Movies/MoviesService.cs

@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Movies
                 .OrderBy(i => Guid.NewGuid())
                 .ToList();
 
-            var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(10).OrderBy(i => Guid.NewGuid()), itemLimit, fields, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
+            var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, fields, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
             var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, fields, RecommendationType.SimilarToLikedItem).GetEnumerator();
 
             var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, fields, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();

+ 32 - 12
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -279,8 +279,19 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <returns>System.Int32.</returns>
         /// <exception cref="System.Exception">Unrecognized MediaEncodingQuality value.</exception>
-        protected int GetNumberOfThreads(bool isWebm)
+        protected int GetNumberOfThreads(StreamState state, bool isWebm)
         {
+            // Use more when this is true. -re will keep cpu usage under control
+            if (state.ReadInputAtNativeFramerate)
+            {
+                if (isWebm)
+                {
+                    return Math.Max(Environment.ProcessorCount - 1, 1);
+                }
+
+                return 0;
+            }
+
             // Webm: http://www.webmproject.org/docs/encoder-parameters/
             // The decoder will usually automatically use an appropriate number of threads according to how many cores are available but it can only use multiple threads 
             // for the coefficient data if the encoder selected --token-parts > 0 at encode time.
@@ -1191,66 +1202,74 @@ namespace MediaBrowser.Api.Playback
                     request.DeviceId = val;
                 }
                 else if (i == 1)
+                {
+                    request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+                }
+                else if (i == 2)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.VideoCodec = (VideoCodecs)Enum.Parse(typeof(VideoCodecs), val, true);
                     }
                 }
-                else if (i == 2)
+                else if (i == 3)
                 {
                     request.AudioCodec = (AudioCodecs)Enum.Parse(typeof(AudioCodecs), val, true);
                 }
-                else if (i == 3)
+                else if (i == 4)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
                     }
                 }
-                else if (i == 4)
+                else if (i == 5)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
                     }
                 }
-                else if (i == 5)
+                else if (i == 6)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.VideoBitRate = int.Parse(val, UsCulture);
                     }
                 }
-                else if (i == 6)
+                else if (i == 7)
                 {
                     request.AudioBitRate = int.Parse(val, UsCulture);
                 }
-                else if (i == 7)
+                else if (i == 8)
                 {
                     request.AudioChannels = int.Parse(val, UsCulture);
                 }
-                else if (i == 8)
+                else if (i == 9)
                 {
                     if (videoRequest != null)
                     {
                         request.StartTimeTicks = long.Parse(val, UsCulture);
                     }
                 }
-                else if (i == 9)
+                else if (i == 10)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.Profile = val;
                     }
                 }
-                else if (i == 10)
+                else if (i == 11)
                 {
                     if (videoRequest != null)
                     {
                         videoRequest.Level = val;
                     }
                 }
+                else if (i == 12)
+                {
+                    request.ForcedMimeType = val;
+                }
             }
         }
 
@@ -1334,6 +1353,7 @@ namespace MediaBrowser.Api.Playback
                     await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
                 }
 
+                state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress;
                 state.AudioSync = "1000";
                 state.DeInterlace = true;
             }
@@ -1420,8 +1440,8 @@ namespace MediaBrowser.Api.Playback
 
             state.HasMediaStreams = mediaStreams.Count > 0;
 
-            state.SegmentLength = state.ReadInputAtNativeFramerate ? 3 : 10;
-            state.HlsListSize = state.ReadInputAtNativeFramerate ? 20 : 1440;
+            state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
+            state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
 
             return state;
         }

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

@@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
             var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds);
 
-            var threads = GetNumberOfThreads(false);
+            var threads = GetNumberOfThreads(state, false);
 
             var inputModifier = GetInputModifier(state);
 

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

@@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Playback.Progressive
 
             const string vn = " -vn";
 
-            var threads = GetNumberOfThreads(false);
+            var threads = GetNumberOfThreads(state, false);
 
             var inputModifier = GetInputModifier(state);
 

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

@@ -214,12 +214,16 @@ namespace MediaBrowser.Api.Playback.Progressive
 
             if (request.Static)
             {
-                return ResultFactory.GetStaticFileResult(Request, state.MediaPath, FileShare.Read, responseHeaders, isHeadRequest);
+                var contentType = state.GetMimeType(state.MediaPath);
+
+                return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
             }
 
             if (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive))
             {
-                return ResultFactory.GetStaticFileResult(Request, outputPath, FileShare.Read, responseHeaders, isHeadRequest);
+                var contentType = state.GetMimeType(outputPath);
+
+                return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
             }
 
             return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
@@ -287,7 +291,7 @@ namespace MediaBrowser.Api.Playback.Progressive
 
             responseHeaders["Accept-Ranges"] = "none";
 
-            var contentType = MimeTypes.GetMimeType(outputPath);
+            var contentType = state.GetMimeType(outputPath);
 
             // Headers only
             if (isHeadRequest)

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

@@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Playback.Progressive
                 format = " -f mp4 -movflags frag_keyframe+empty_moov";
             }
 
-            var threads = GetNumberOfThreads(string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase));
+            var threads = GetNumberOfThreads(state, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase));
 
             var inputModifier = GetInputModifier(state);
 

+ 2 - 0
MediaBrowser.Api/Playback/StreamRequest.cs

@@ -66,6 +66,8 @@ namespace MediaBrowser.Api.Playback
         public bool ThrowDebugError { get; set; }
 
         public string Params { get; set; }
+
+        public string ForcedMimeType { get; set; }
     }
 
     public class VideoStreamRequest : StreamRequest

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

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using System.Collections.Generic;
 using System.IO;
@@ -72,5 +73,20 @@ namespace MediaBrowser.Api.Playback
         public string InputVideoCodec { get; set; }
 
         public string InputAudioCodec { get; set; }
+
+        public string GetMimeType(string outputPath)
+        {
+            if (!string.IsNullOrWhiteSpace(Request.ForcedMimeType))
+            {
+                if (VideoRequest == null)
+                {
+                    return "audio/" + Request.ForcedMimeType;
+                }
+
+                return "video/" + Request.ForcedMimeType;
+            }
+
+            return MimeTypes.GetMimeType(outputPath);
+        }
     }
 }

+ 2 - 2
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1184,7 +1184,7 @@ namespace MediaBrowser.Controller.Entities
             return GetImageInfo(type, imageIndex) != null;
         }
 
-        public void SetImagePath(ImageType type, int index, FileInfo file)
+        public void SetImagePath(ImageType type, int index, FileSystemInfo file)
         {
             if (type == ImageType.Chapter)
             {
@@ -1339,7 +1339,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="images">The images.</param>
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
         /// <exception cref="System.ArgumentException">Cannot call AddImages with chapter images</exception>
-        public bool AddImages(ImageType imageType, IEnumerable<FileInfo> images)
+        public bool AddImages(ImageType imageType, IEnumerable<FileSystemInfo> images)
         {
             if (imageType == ImageType.Chapter)
             {

+ 3 - 3
MediaBrowser.Controller/Entities/IHasImages.cs

@@ -62,7 +62,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="type">The type.</param>
         /// <param name="index">The index.</param>
         /// <param name="file">The file.</param>
-        void SetImagePath(ImageType type, int index, FileInfo file);
+        void SetImagePath(ImageType type, int index, FileSystemInfo file);
 
         /// <summary>
         /// Determines whether the specified type has image.
@@ -129,7 +129,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="imageType">Type of the image.</param>
         /// <param name="images">The images.</param>
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
-        bool AddImages(ImageType imageType, IEnumerable<FileInfo> images);
+        bool AddImages(ImageType imageType, IEnumerable<FileSystemInfo> images);
 
         /// <summary>
         /// Determines whether [is save local metadata enabled].
@@ -180,7 +180,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="item">The item.</param>
         /// <param name="imageType">Type of the image.</param>
         /// <param name="file">The file.</param>
-        public static void SetImagePath(this IHasImages item, ImageType imageType, FileInfo file)
+        public static void SetImagePath(this IHasImages item, ImageType imageType, FileSystemInfo file)
         {
             item.SetImagePath(imageType, 0, file);
         }

+ 80 - 80
MediaBrowser.Controller/Library/TVUtils.cs

@@ -27,94 +27,94 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// A season folder must contain one of these somewhere in the name
         /// </summary>
-        private static readonly string[] SeasonFolderNames = new[]
-                                                                 {
-                                                                     "season",
-                                                                     "sæson",
-                                                                     "temporada",
-                                                                     "saison",
-                                                                     "staffel",
-                                                                     "series",
-                                                                     "сезон"
-                                                                 };
+        private static readonly string[] SeasonFolderNames =
+        {
+            "season",
+            "sæson",
+            "temporada",
+            "saison",
+            "staffel",
+            "series",
+            "сезон"
+        };
 
         /// <summary>
         /// Used to detect paths that represent episodes, need to make sure they don't also
         /// match movie titles like "2001 A Space..."
         /// Currently we limit the numbers here to 2 digits to try and avoid this
         /// </summary>
-        private static readonly Regex[] EpisodeExpressions = new[]
-                                                                 {
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS](?<seasonnumber>\d{1,4})[x,X]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
-                                                                         RegexOptions.Compiled)
-                                                                 };
-        private static readonly Regex[] MultipleEpisodeExpressions = new[]
-                                                                 {
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled),
-                                                                     new Regex(
-                                                                         @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
-                                                                         RegexOptions.Compiled)
-                                                                 };
+        private static readonly Regex[] EpisodeExpressions =
+        {
+            new Regex(
+                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)[sS](?<seasonnumber>\d{1,4})[x,X]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
+                RegexOptions.Compiled)
+        };
+        private static readonly Regex[] MultipleEpisodeExpressions =
+        {
+            new Regex(
+                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled),
+            new Regex(
+                @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
+                RegexOptions.Compiled)
+        };
 
         /// <summary>
         /// To avoid the following matching movies they are only valid when contained in a folder which has been matched as a being season
         /// </summary>
-        private static readonly Regex[] EpisodeExpressionsInASeasonFolder = new[]
-                                                                                {
-                                                                                    new Regex(
-                                                                                        @".*(\\|\/)(?<epnumber>\d{1,2})\s?-\s?[^\\\/]*$",
-                                                                                        RegexOptions.Compiled),
-                                                                                    // 01 - blah.avi, 01-blah.avi
-                                                                                    new Regex(
-                                                                                        @".*(\\|\/)(?<epnumber>\d{1,2})[^\d\\]*[^\\\/]*$",
-                                                                                        RegexOptions.Compiled),
-                                                                                    // 01.avi, 01.blah.avi "01 - 22 blah.avi" 
-                                                                                    new Regex(
-                                                                                        @".*(\\|\/)(?<seasonnumber>\d)(?<epnumber>\d{1,2})[^\d\\]+[^\\\/]*$",
-                                                                                        RegexOptions.Compiled),
-                                                                                    // 01.avi, 01.blah.avi
-                                                                                    new Regex(
-                                                                                        @".*(\\|\/)\D*\d+(?<epnumber>\d{2})",
-                                                                                        RegexOptions.Compiled)
-                                                                                    // hell0 - 101 -  hello.avi
-
-                                                                                };
+        private static readonly Regex[] EpisodeExpressionsInASeasonFolder =
+        {
+            new Regex(
+                @".*(\\|\/)(?<epnumber>\d{1,2})\s?-\s?[^\\\/]*$",
+                RegexOptions.Compiled),
+            // 01 - blah.avi, 01-blah.avi
+            new Regex(
+                @".*(\\|\/)(?<epnumber>\d{1,2})[^\d\\]*[^\\\/]*$",
+                RegexOptions.Compiled),
+            // 01.avi, 01.blah.avi "01 - 22 blah.avi" 
+            new Regex(
+                @".*(\\|\/)(?<seasonnumber>\d)(?<epnumber>\d{1,2})[^\d\\]+[^\\\/]*$",
+                RegexOptions.Compiled),
+            // 01.avi, 01.blah.avi
+            new Regex(
+                @".*(\\|\/)\D*\d+(?<epnumber>\d{2})",
+                RegexOptions.Compiled)
+            // hell0 - 101 -  hello.avi
+
+        };
 
         /// <summary>
         /// Gets the season number from path.
@@ -151,8 +151,8 @@ namespace MediaBrowser.Controller.Library
         /// <returns>System.Nullable{System.Int32}.</returns>
         private static int? GetSeasonNumberFromPathSubstring(string path)
         {
-            int numericStart = -1;
-            int length = 0;
+            var numericStart = -1;
+            var length = 0;
 
             // Find out where the numbers start, and then keep going until they end
             for (var i = 0; i < path.Length; i++)

+ 12 - 0
MediaBrowser.Controller/Net/IHttpResultFactory.cs

@@ -95,6 +95,18 @@ namespace MediaBrowser.Controller.Net
         /// <returns>System.Object.</returns>
         object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
 
+        /// <summary>
+        /// Gets the static file result.
+        /// </summary>
+        /// <param name="requestContext">The request context.</param>
+        /// <param name="path">The path.</param>
+        /// <param name="contentType">Type of the content.</param>
+        /// <param name="fileShare">The file share.</param>
+        /// <param name="responseHeaders">The response headers.</param>
+        /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
+        /// <returns>System.Object.</returns>
+        object GetStaticFileResult(IRequest requestContext, string path, string contentType, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
+        
         /// <summary>
         /// Gets the optimized serialized result using cache.
         /// </summary>

+ 7 - 23
MediaBrowser.Controller/Providers/DirectoryService.cs

@@ -1,6 +1,6 @@
-using System.Collections.Concurrent;
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Logging;
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -10,10 +10,8 @@ namespace MediaBrowser.Controller.Providers
     public interface IDirectoryService
     {
         List<FileSystemInfo> GetFileSystemEntries(string path);
-        IEnumerable<FileInfo> GetFiles(string path);
-        IEnumerable<DirectoryInfo> GetDirectories(string path);
-        FileInfo GetFile(string path);
-        DirectoryInfo GetDirectory(string path);
+        IEnumerable<FileSystemInfo> GetFiles(string path);
+        FileSystemInfo GetFile(string path);
     }
 
     public class DirectoryService : IDirectoryService
@@ -50,31 +48,17 @@ namespace MediaBrowser.Controller.Providers
             return entries;
         }
 
-        public IEnumerable<FileInfo> GetFiles(string path)
+        public IEnumerable<FileSystemInfo> GetFiles(string path)
         {
-            return GetFileSystemEntries(path).OfType<FileInfo>();
+            return GetFileSystemEntries(path).Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory);
         }
 
-        public IEnumerable<DirectoryInfo> GetDirectories(string path)
-        {
-            return GetFileSystemEntries(path).OfType<DirectoryInfo>();
-        }
-
-        public FileInfo GetFile(string path)
+        public FileSystemInfo GetFile(string path)
         {
             var directory = Path.GetDirectoryName(path);
             var filename = Path.GetFileName(path);
 
             return GetFiles(directory).FirstOrDefault(i => string.Equals(i.Name, filename, StringComparison.OrdinalIgnoreCase));
         }
-
-
-        public DirectoryInfo GetDirectory(string path)
-        {
-            var directory = Path.GetDirectoryName(path);
-            var name = Path.GetFileName(path);
-
-            return GetDirectories(directory).FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
-        }
     }
 }

+ 1 - 1
MediaBrowser.Controller/Providers/ILocalImageProvider.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers
 
     public class LocalImageInfo
     {
-        public FileInfo FileInfo { get; set; }
+        public FileSystemInfo FileInfo { get; set; }
         public ImageType Type { get; set; }
     }
 

+ 1 - 1
MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.AdultVideos
             new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
         }

+ 1 - 1
MediaBrowser.Providers/All/LocalImageProvider.cs

@@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.All
             PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop);
             PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop);
 
-            var extraFanartFolder = files.OfType<DirectoryInfo>()
+            var extraFanartFolder = files
                 .FirstOrDefault(i => string.Equals(i.Name, "extrafanart", StringComparison.OrdinalIgnoreCase));
 
             if (extraFanartFolder != null)

+ 1 - 1
MediaBrowser.Providers/BaseXmlProvider.cs

@@ -59,7 +59,7 @@ namespace MediaBrowser.Providers
             FileSystem = fileSystem;
         }
 
-        protected abstract FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService);
+        protected abstract FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService);
 
         public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
         {

+ 1 - 1
MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.BoxSets
             new BoxSetXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "collection.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/Folders/FolderXmlProvider.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Folders
             new BaseItemXmlParser<Folder>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return new FileInfo(Path.Combine(info.Path, "folder.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/Games/GameSystemXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Games
             new GameSystemXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "gamesystem.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/Games/GameXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Games
             new GameXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             var fileInfo = FileSystem.GetFileSystemInfo(info.Path);
 

+ 1 - 1
MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.LiveTv
             new BaseItemXmlParser<LiveTvChannel>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "channel.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -357,7 +357,7 @@ namespace MediaBrowser.Providers.MediaInfo
             }
         }
 
-        public IEnumerable<FileInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService)
+        public IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService)
         {
             var containingPath = video.ContainingFolderPath;
 

+ 1 - 1
MediaBrowser.Providers/Movies/MovieXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Movies
             new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return GetXmlFileInfo(info, FileSystem);
         }

+ 1 - 1
MediaBrowser.Providers/Movies/TrailerXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Movies
             new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
         }

+ 1 - 1
MediaBrowser.Providers/Music/AlbumXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Music
             new BaseItemXmlParser<MusicAlbum>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "album.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/Music/ArtistXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Music
             new BaseItemXmlParser<MusicArtist>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "artist.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs

@@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.Music
             new MusicVideoXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
         }

+ 1 - 1
MediaBrowser.Providers/People/PersonXmlProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.People
             new BaseItemXmlParser<Person>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "person.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/TV/EpisodeXmlProvider.cs

@@ -27,7 +27,7 @@ namespace MediaBrowser.Providers.TV
             result.Images = images;
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             var metadataPath = Path.GetDirectoryName(info.Path);
             metadataPath = Path.Combine(metadataPath, "metadata");

+ 1 - 1
MediaBrowser.Providers/TV/SeasonXmlProvider.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV
             new BaseItemXmlParser<Season>(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "season.xml"));
         }

+ 1 - 1
MediaBrowser.Providers/TV/SeriesXmlProvider.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV
             new SeriesXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
         }
 
-        protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
         {
             return directoryService.GetFile(Path.Combine(info.Path, "series.xml"));
         }

+ 5 - 7
MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs

@@ -173,25 +173,23 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
 
             if (!overwriteExisting)
             {
-                if (fileExists || otherDuplicatePaths.Count > 0)
+                if (options.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath))
                 {
+                    _logger.Info("File {0} already copied to new path {1}, stopping organization", sourcePath, newPath);
                     result.Status = FileSortingStatus.SkippedExisting;
                     result.StatusMessage = string.Empty;
-                    result.DuplicatePaths = otherDuplicatePaths;
                     return;
                 }
-
-                if (options.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath))
+                
+                if (fileExists || otherDuplicatePaths.Count > 0)
                 {
-                    _logger.Info("File {0} already copied to new path {1}, stopping organization", sourcePath, newPath);
                     result.Status = FileSortingStatus.SkippedExisting;
                     result.StatusMessage = string.Empty;
+                    result.DuplicatePaths = otherDuplicatePaths;
                     return;
                 }
             }
 
-   
-
             PerformFileSorting(options, result);
 
             if (overwriteExisting)

+ 13 - 1
MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -306,6 +306,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                 throw new ArgumentNullException("path");
             }
 
+            return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), fileShare, responseHeaders, isHeadRequest);
+        }
+
+        public object GetStaticFileResult(IRequest requestContext, string path, string contentType,
+            FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null,
+            bool isHeadRequest = false)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
             if (fileShare != FileShare.Read && fileShare != FileShare.ReadWrite)
             {
                 throw new ArgumentException("FileShare must be either Read or ReadWrite");
@@ -315,7 +327,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
             var cacheKey = path + dateModified.Ticks;
 
-            return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, MimeTypes.GetMimeType(path), () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest);
+            return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest);
         }
 
         /// <summary>

+ 0 - 15
MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -56,21 +56,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                 {
                     return null;
                 }
-
-                // If the parent is not a boxset, the only other allowed parent type is Folder		
-                if (!(args.Parent is BoxSet))
-                {
-                    if (args.Parent.GetType() != typeof(Folder))
-                    {
-                        return null;
-                    }
-                }
-            }
-
-            // Since the looping is expensive, this is an optimization to help us avoid it
-            if (args.Path.IndexOf("[tvdbid", StringComparison.OrdinalIgnoreCase) != -1)
-            {
-                return null;
             }
 
             var isDirectory = args.IsDirectory;