فهرست منبع

Merge remote-tracking branch 'upstream/master' into docker

HurricaneHernandez 10 سال پیش
والد
کامیت
e01f932f4b
100فایلهای تغییر یافته به همراه1308 افزوده شده و 862 حذف شده
  1. 1 42
      MediaBrowser.Api/ConfigurationService.cs
  2. 4 4
      MediaBrowser.Api/Devices/DeviceService.cs
  3. 1 1
      MediaBrowser.Api/ItemUpdateService.cs
  4. 91 2
      MediaBrowser.Api/Movies/TrailersService.cs
  5. 6 2
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  6. 2 12
      MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
  7. 1 1
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  8. 13 15
      MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
  9. 1 17
      MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
  10. 19 1
      MediaBrowser.Api/Playback/StreamState.cs
  11. 3 1
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  12. 10 0
      MediaBrowser.Common.Implementations/BaseApplicationHost.cs
  13. 58 58
      MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
  14. 4 0
      MediaBrowser.Common/Net/HttpRequestOptions.cs
  15. 2 0
      MediaBrowser.Controller/Connect/UserLinkResult.cs
  16. 0 10
      MediaBrowser.Controller/Dto/IDtoService.cs
  17. 3 1
      MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
  18. 7 1
      MediaBrowser.Controller/Entities/BaseItem.cs
  19. 2 1
      MediaBrowser.Controller/Entities/CollectionFolder.cs
  20. 36 2
      MediaBrowser.Controller/Entities/Folder.cs
  21. 13 27
      MediaBrowser.Controller/Entities/MusicVideo.cs
  22. 10 1
      MediaBrowser.Controller/Entities/TV/Episode.cs
  23. 6 0
      MediaBrowser.Controller/Entities/TV/Season.cs
  24. 11 19
      MediaBrowser.Controller/Library/ILibraryManager.cs
  25. 0 1
      MediaBrowser.Controller/Library/IMetadataSaver.cs
  26. 7 25
      MediaBrowser.Controller/Library/ItemResolveArgs.cs
  27. 1 1
      MediaBrowser.Controller/Library/TVUtils.cs
  28. 9 2
      MediaBrowser.Controller/Persistence/IItemRepository.cs
  29. 0 4
      MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
  30. 1 1
      MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
  31. 6 0
      MediaBrowser.Controller/Session/SessionInfo.cs
  32. 110 33
      MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
  33. 84 43
      MediaBrowser.Dlna/Didl/DidlBuilder.cs
  34. 63 40
      MediaBrowser.Dlna/DlnaManager.cs
  35. 4 0
      MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
  36. 36 32
      MediaBrowser.Dlna/PlayTo/PlayToController.cs
  37. 11 0
      MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
  38. 178 0
      MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
  39. 1 8
      MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
  40. 1 1
      MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
  41. 2 0
      MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs
  42. 1 0
      MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs
  43. 1 0
      MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs
  44. 1 0
      MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs
  45. 43 22
      MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
  46. 32 3
      MediaBrowser.Dlna/Profiles/XboxOneProfile.cs
  47. 22 9
      MediaBrowser.Dlna/Profiles/Xml/Android.xml
  48. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Default.xml
  49. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
  50. 3 0
      MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
  51. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
  52. 3 0
      MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
  53. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
  54. 3 0
      MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
  55. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
  56. 24 0
      MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
  57. 3 1
      MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
  58. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
  59. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
  60. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
  61. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
  62. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
  63. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
  64. 9 8
      MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
  65. 3 0
      MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
  66. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml
  67. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml
  68. 3 0
      MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
  69. 1 0
      MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
  70. 3 0
      MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
  71. 1 0
      MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
  72. 14 4
      MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
  73. 2 2
      MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
  74. 7 0
      MediaBrowser.MediaInfo/MediaInfoLib.cs
  75. 3 3
      MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
  76. 3 3
      MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
  77. 5 3
      MediaBrowser.Model/ApiClient/IConnectionManager.cs
  78. 5 0
      MediaBrowser.Model/Configuration/MetadataConfiguration.cs
  79. 2 0
      MediaBrowser.Model/Configuration/ServerConfiguration.cs
  80. 3 0
      MediaBrowser.Model/Configuration/UserConfiguration.cs
  81. 1 1
      MediaBrowser.Model/Devices/LocalFileInfo.cs
  82. 3 0
      MediaBrowser.Model/Dlna/ConditionProcessor.cs
  83. 2 0
      MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
  84. 4 1
      MediaBrowser.Model/Dlna/DeviceProfile.cs
  85. 2 1
      MediaBrowser.Model/Dlna/ProfileConditionValue.cs
  86. 10 3
      MediaBrowser.Model/Dlna/Profiles/AndroidProfile.cs
  87. 4 2
      MediaBrowser.Model/Dlna/StreamBuilder.cs
  88. 13 0
      MediaBrowser.Model/Dlna/StreamInfo.cs
  89. 9 2
      MediaBrowser.Model/Dto/BaseItemDto.cs
  90. 8 0
      MediaBrowser.Model/Dto/IHasServerId.cs
  91. 7 1
      MediaBrowser.Model/Dto/UserDto.cs
  92. 6 0
      MediaBrowser.Model/Entities/MediaStream.cs
  93. 1 1
      MediaBrowser.Model/MediaBrowser.Model.csproj
  94. 1 20
      MediaBrowser.Model/Querying/ItemsResult.cs
  95. 0 17
      MediaBrowser.Model/Weather/WeatherUnits.cs
  96. 1 0
      MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
  97. 22 6
      MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
  98. 99 206
      MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
  99. 3 5
      MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
  100. 55 129
      MediaBrowser.Providers/TV/FanArtSeasonProvider.cs

+ 1 - 42
MediaBrowser.Api/ConfigurationService.cs

@@ -122,53 +122,12 @@ namespace MediaBrowser.Api
             return ToOptimizedResult(result);
             return ToOptimizedResult(result);
         }
         }
 
 
-        const string XbmcMetadata = "Xbmc Nfo";
-        const string MediaBrowserMetadata = "Media Browser Xml";
-
         public void Post(AutoSetMetadataOptions request)
         public void Post(AutoSetMetadataOptions request)
         {
         {
-            var service = AutoDetectMetadataService();
-
-            Logger.Info("Setting preferred metadata format to " + service);
-
-            var serviceToDisable = string.Equals(service, XbmcMetadata) ?
-                MediaBrowserMetadata :
-                XbmcMetadata;
-
-            _configurationManager.DisableMetadataService(serviceToDisable);
+            _configurationManager.DisableMetadataService("Media Browser Xml");
             _configurationManager.SaveConfiguration();
             _configurationManager.SaveConfiguration();
         }
         }
 
 
-        private string AutoDetectMetadataService()
-        {
-            try
-            {
-                var paths = _libraryManager.GetDefaultVirtualFolders()
-                   .SelectMany(i => i.Locations)
-                   .Distinct(StringComparer.OrdinalIgnoreCase)
-                   .Select(i => new DirectoryInfo(i))
-                   .ToList();
-
-                if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
-                    .Any())
-                {
-                    return XbmcMetadata;
-                }
-
-                if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
-                    .Any(i => string.Equals(i.Name, "series.xml", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "movie.xml", StringComparison.OrdinalIgnoreCase)))
-                {
-                    return MediaBrowserMetadata;
-                }
-            }
-            catch (Exception)
-            {
-                
-            }
-            
-            return XbmcMetadata;
-        }
-
         /// <summary>
         /// <summary>
         /// Posts the specified configuraiton.
         /// Posts the specified configuraiton.
         /// </summary>
         /// </summary>

+ 4 - 4
MediaBrowser.Api/Devices/DeviceService.cs

@@ -44,8 +44,8 @@ namespace MediaBrowser.Api.Devices
         [ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
         [ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string Name { get; set; }
         public string Name { get; set; }
 
 
-        [ApiMember(Name = "FullPath", Description = "FullPath", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string FullPath { get; set; }
+        [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string Id { get; set; }
 
 
         public Stream RequestStream { get; set; }
         public Stream RequestStream { get; set; }
     }
     }
@@ -132,7 +132,7 @@ namespace MediaBrowser.Api.Devices
         {
         {
             var deviceId = Request.QueryString["DeviceId"];
             var deviceId = Request.QueryString["DeviceId"];
             var album = Request.QueryString["Album"];
             var album = Request.QueryString["Album"];
-            var fullPath = Request.QueryString["FullPath"];
+            var id = Request.QueryString["Id"];
             var name = Request.QueryString["Name"];
             var name = Request.QueryString["Name"];
 
 
             var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
             var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
@@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Devices
                 MimeType = Request.ContentType,
                 MimeType = Request.ContentType,
                 Album = album,
                 Album = album,
                 Name = name,
                 Name = name,
-                FullPath = fullPath
+                Id = id
             });
             });
 
 
             Task.WaitAll(task);
             Task.WaitAll(task);

+ 1 - 1
MediaBrowser.Api/ItemUpdateService.cs

@@ -237,7 +237,7 @@ namespace MediaBrowser.Api
 
 
             if (musicVideo != null)
             if (musicVideo != null)
             {
             {
-                musicVideo.Artist = request.Artists[0];
+                musicVideo.Artists = request.Artists.ToList();
                 musicVideo.Album = request.Album;
                 musicVideo.Album = request.Album;
             }
             }
 
 

+ 91 - 2
MediaBrowser.Api/Movies/TrailersService.cs

@@ -1,10 +1,20 @@
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Api.UserLibrary;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
 using ServiceStack;
 using ServiceStack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.Movies
 namespace MediaBrowser.Api.Movies
 {
 {
@@ -16,6 +26,17 @@ namespace MediaBrowser.Api.Movies
     {
     {
     }
     }
 
 
+    [Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
+    public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
+    {
+        /// <summary>
+        /// Gets or sets the user id.
+        /// </summary>
+        /// <value>The user id.</value>
+        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
+        public Guid? UserId { get; set; }
+    }
+
     /// <summary>
     /// <summary>
     /// Class TrailersService
     /// Class TrailersService
     /// </summary>
     /// </summary>
@@ -38,6 +59,7 @@ namespace MediaBrowser.Api.Movies
 
 
         private readonly IItemRepository _itemRepo;
         private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
         private readonly IDtoService _dtoService;
+        private readonly IChannelManager _channelManager;
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="TrailersService"/> class.
         /// Initializes a new instance of the <see cref="TrailersService"/> class.
@@ -45,13 +67,14 @@ namespace MediaBrowser.Api.Movies
         /// <param name="userManager">The user manager.</param>
         /// <param name="userManager">The user manager.</param>
         /// <param name="userDataRepository">The user data repository.</param>
         /// <param name="userDataRepository">The user data repository.</param>
         /// <param name="libraryManager">The library manager.</param>
         /// <param name="libraryManager">The library manager.</param>
-        public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
+        public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager)
         {
         {
             _userManager = userManager;
             _userManager = userManager;
             _userDataRepository = userDataRepository;
             _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
             _itemRepo = itemRepo;
             _itemRepo = itemRepo;
             _dtoService = dtoService;
             _dtoService = dtoService;
+            _channelManager = channelManager;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -75,5 +98,71 @@ namespace MediaBrowser.Api.Movies
 
 
             return ToOptimizedSerializedResultUsingCache(result);
             return ToOptimizedSerializedResultUsingCache(result);
         }
         }
+
+        public async Task<object> Get(Getrailers request)
+        {
+            var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
+            var result = await GetAllTrailers(user).ConfigureAwait(false);
+
+            IEnumerable<BaseItem> items = result.Items;
+
+            // Apply filters
+            // Run them starting with the ones that are likely to reduce the list the most
+            foreach (var filter in request.GetFilters().OrderByDescending(f => (int)f))
+            {
+                items = ItemsService.ApplyFilter(items, filter, user, _userDataRepository);
+            }
+
+            items = _libraryManager.Sort(items, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
+
+            var itemsArray = items.ToList();
+
+            var pagedItems = ApplyPaging(request, itemsArray);
+
+            var fields = request.GetItemFields().ToList();
+
+            var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray();
+
+            return new ItemsResult
+            {
+                TotalRecordCount = itemsArray.Count,
+                Items = returnItems
+            };
+        }
+
+        private IEnumerable<BaseItem> ApplyPaging(Getrailers request, IEnumerable<BaseItem> items)
+        {
+            // Start at
+            if (request.StartIndex.HasValue)
+            {
+                items = items.Skip(request.StartIndex.Value);
+            }
+
+            // Return limit
+            if (request.Limit.HasValue)
+            {
+                items = items.Take(request.Limit.Value);
+            }
+
+            return items;
+        }
+
+        private async Task<QueryResult<BaseItem>> GetAllTrailers(User user)
+        {
+            var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
+            {
+                ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
+                ExtraTypes = new[] { ExtraType.Trailer },
+                UserId = user.Id.ToString("N")
+
+            }, CancellationToken.None).ConfigureAwait(false);
+
+
+            return new QueryResult<BaseItem>
+            {
+                Items = trailerResult.Items,
+                TotalRecordCount = trailerResult.TotalRecordCount
+            };
+        }
     }
     }
 }
 }

+ 6 - 2
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -714,8 +714,10 @@ namespace MediaBrowser.Api.Playback
         /// <returns><c>true</c> if the specified stream is H264; otherwise, <c>false</c>.</returns>
         /// <returns><c>true</c> if the specified stream is H264; otherwise, <c>false</c>.</returns>
         protected bool IsH264(MediaStream stream)
         protected bool IsH264(MediaStream stream)
         {
         {
-            return stream.Codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
-                   stream.Codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
+            var codec = stream.Codec ?? string.Empty;
+
+            return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
+                   codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1976,6 +1978,7 @@ namespace MediaBrowser.Api.Playback
                 state.TargetPacketLength,
                 state.TargetPacketLength,
                 state.TargetTimestamp,
                 state.TargetTimestamp,
                 state.IsTargetAnamorphic,
                 state.IsTargetAnamorphic,
+                state.IsTargetCabac,
                 state.TargetRefFrames);
                 state.TargetRefFrames);
 
 
             if (mediaProfile != null)
             if (mediaProfile != null)
@@ -2065,6 +2068,7 @@ namespace MediaBrowser.Api.Playback
                     state.TargetPacketLength,
                     state.TargetPacketLength,
                     state.TranscodeSeekInfo,
                     state.TranscodeSeekInfo,
                     state.IsTargetAnamorphic,
                     state.IsTargetAnamorphic,
+                    state.IsTargetCabac,
                     state.TargetRefFrames
                     state.TargetRefFrames
 
 
                     ).FirstOrDefault() ?? string.Empty;
                     ).FirstOrDefault() ?? string.Empty;

+ 2 - 12
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -367,16 +367,6 @@ namespace MediaBrowser.Api.Playback.Hls
         {
         {
             var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
             var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
 
 
-            if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
-            {
-                throw new ArgumentException("Audio codec copy is not allowed here.");
-            }
-
-            if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
-            {
-                throw new ArgumentException("Video codec copy is not allowed here.");
-            }
-
             if (string.IsNullOrEmpty(request.MediaSourceId))
             if (string.IsNullOrEmpty(request.MediaSourceId))
             {
             {
                 throw new ArgumentException("MediaSourceId is required");
                 throw new ArgumentException("MediaSourceId is required");
@@ -511,7 +501,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
 
         private void AppendPlaylist(StringBuilder builder, string url, int bitrate, string subtitleGroup)
         private void AppendPlaylist(StringBuilder builder, string url, int bitrate, string subtitleGroup)
         {
         {
-            var header = "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate.ToString(UsCulture);
+            var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(UsCulture);
 
 
             if (!string.IsNullOrWhiteSpace(subtitleGroup))
             if (!string.IsNullOrWhiteSpace(subtitleGroup))
             {
             {
@@ -638,7 +628,7 @@ namespace MediaBrowser.Api.Playback.Hls
             // See if we can save come cpu cycles by avoiding encoding
             // See if we can save come cpu cycles by avoiding encoding
             if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
             if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
             {
             {
-                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
+                return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
             }
             }
 
 
             var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
             var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",

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

@@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Hls
             // See if we can save come cpu cycles by avoiding encoding
             // See if we can save come cpu cycles by avoiding encoding
             if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
             if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
             {
             {
-                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
+                return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
             }
             }
 
 
             var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
             var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",

+ 13 - 15
MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs

@@ -1,5 +1,4 @@
-using System.Threading;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using ServiceStack.Web;
 using ServiceStack.Web;
 using System;
 using System;
@@ -49,9 +48,7 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// <param name="responseStream">The response stream.</param>
         /// <param name="responseStream">The response stream.</param>
         public void WriteTo(Stream responseStream)
         public void WriteTo(Stream responseStream)
         {
         {
-            var task = WriteToAsync(responseStream);
-
-            Task.WaitAll(task);
+            WriteToInternal(responseStream);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -59,12 +56,12 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// </summary>
         /// </summary>
         /// <param name="responseStream">The response stream.</param>
         /// <param name="responseStream">The response stream.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        public async Task WriteToAsync(Stream responseStream)
+        private void WriteToInternal(Stream responseStream)
         {
         {
             try
             try
             {
             {
-                await new ProgressiveFileCopier(_fileSystem, _job)
-                    .StreamFile(Path, responseStream).ConfigureAwait(false);
+                new ProgressiveFileCopier(_fileSystem, _job)
+                    .StreamFile(Path, responseStream);
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -95,16 +92,16 @@ namespace MediaBrowser.Api.Playback.Progressive
             _job = job;
             _job = job;
         }
         }
 
 
-        public async Task StreamFile(string path, Stream outputStream)
+        public void StreamFile(string path, Stream outputStream)
         {
         {
             var eofCount = 0;
             var eofCount = 0;
             long position = 0;
             long position = 0;
 
 
-            using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+            using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, false))
             {
             {
                 while (eofCount < 15)
                 while (eofCount < 15)
                 {
                 {
-                    await CopyToAsyncInternal(fs, outputStream, 81920, CancellationToken.None).ConfigureAwait(false);
+                    CopyToInternal(fs, outputStream, 81920);
 
 
                     var fsPosition = fs.Position;
                     var fsPosition = fs.Position;
 
 
@@ -118,7 +115,8 @@ namespace MediaBrowser.Api.Playback.Progressive
                         {
                         {
                             eofCount++;
                             eofCount++;
                         }
                         }
-                        await Task.Delay(100).ConfigureAwait(false);
+                        var task = Task.Delay(100);
+                        Task.WaitAll(task);
                     }
                     }
                     else
                     else
                     {
                     {
@@ -130,13 +128,13 @@ namespace MediaBrowser.Api.Playback.Progressive
             }
             }
         }
         }
 
 
-        private async Task CopyToAsyncInternal(Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken)
+        private void CopyToInternal(Stream source, Stream destination, int bufferSize)
         {
         {
             byte[] array = new byte[bufferSize];
             byte[] array = new byte[bufferSize];
             int count;
             int count;
-            while ((count = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
+            while ((count = source.Read(array, 0, array.Length)) != 0)
             {
             {
-                await destination.WriteAsync(array, 0, count, cancellationToken).ConfigureAwait(false);
+                destination.Write(array, 0, count);
 
 
                 _bytesWritten += count;
                 _bytesWritten += count;
 
 

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

@@ -2,7 +2,6 @@
 using ServiceStack.Web;
 using ServiceStack.Web;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
-using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.Playback
 namespace MediaBrowser.Api.Playback
 {
 {
@@ -41,22 +40,7 @@ namespace MediaBrowser.Api.Playback
         /// <param name="responseStream">The response stream.</param>
         /// <param name="responseStream">The response stream.</param>
         public void WriteTo(Stream responseStream)
         public void WriteTo(Stream responseStream)
         {
         {
-            var task = WriteToAsync(responseStream);
-
-            Task.WaitAll(task);
-        }
-
-        /// <summary>
-        /// Writes to async.
-        /// </summary>
-        /// <param name="responseStream">The response stream.</param>
-        /// <returns>Task.</returns>
-        public async Task WriteToAsync(Stream responseStream)
-        {
-            using (_response)
-            {
-                await _response.Content.CopyToAsync(responseStream, 819200).ConfigureAwait(false);
-            }
+            _response.Content.CopyTo(responseStream, 819200);
         }
         }
     }
     }
 }
 }

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

@@ -97,7 +97,12 @@ namespace MediaBrowser.Api.Playback
 
 
         public bool ReadInputAtNativeFramerate
         public bool ReadInputAtNativeFramerate
         {
         {
-            get { return InputProtocol == MediaProtocol.Rtmp || string.Equals(InputContainer, "wtv", StringComparison.OrdinalIgnoreCase); }
+            get { 
+                
+                return InputProtocol == MediaProtocol.Rtmp || 
+                    string.Equals(InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) ||
+                    !string.IsNullOrEmpty(LiveTvStreamId); 
+            }
         }
         }
 
 
         public TransportStreamTimestamp InputTimestamp { get; set; }
         public TransportStreamTimestamp InputTimestamp { get; set; }
@@ -413,5 +418,18 @@ namespace MediaBrowser.Api.Playback
                 return false;
                 return false;
             }
             }
         }
         }
+
+        public bool? IsTargetCabac
+        {
+            get
+            {
+                if (Request.Static)
+                {
+                    return VideoStream == null ? null : VideoStream.IsCabac;
+                }
+
+                return true;
+            }
+        }
     }
     }
 }
 }

+ 3 - 1
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Collections;
+using System.Threading;
+using MediaBrowser.Controller.Collections;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.Audio;
@@ -8,6 +9,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using ServiceStack;
 using ServiceStack;

+ 10 - 0
MediaBrowser.Common.Implementations/BaseApplicationHost.cs

@@ -296,6 +296,16 @@ namespace MediaBrowser.Common.Implementations
             logger.Info("64-Bit Process: {0}", Environment.Is64BitProcess);
             logger.Info("64-Bit Process: {0}", Environment.Is64BitProcess);
             logger.Info("Program data path: {0}", appPaths.ProgramDataPath);
             logger.Info("Program data path: {0}", appPaths.ProgramDataPath);
 
 
+            Type type = Type.GetType("Mono.Runtime");
+            if (type != null)
+            {
+                MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
+                if (displayName != null)
+                {
+                    logger.Info("Mono: " + displayName.Invoke(null, null));
+                }
+            } 
+            
             logger.Info("Application Path: {0}", appPaths.ApplicationPath);
             logger.Info("Application Path: {0}", appPaths.ApplicationPath);
 
 
             logger.Info("*** When reporting issues please include the entire log file. ***".ToUpper());
             logger.Info("*** When reporting issues please include the entire log file. ***".ToUpper());

+ 58 - 58
MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -123,7 +123,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
             }
             }
 
 
             request.Method = method;
             request.Method = method;
-            request.Timeout = 20000;
+            request.Timeout = options.TimeoutMs;
 
 
             if (!string.IsNullOrEmpty(options.Host))
             if (!string.IsNullOrEmpty(options.Host))
             {
             {
@@ -390,7 +390,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
 
 
                 if (!options.BufferContent)
                 if (!options.BufferContent)
                 {
                 {
-                    var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false);
+                    var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false);
 
 
                     var httpResponse = (HttpWebResponse)response;
                     var httpResponse = (HttpWebResponse)response;
 
 
@@ -401,7 +401,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
                     return GetResponseInfo(httpResponse, httpResponse.GetResponseStream(), GetContentLength(httpResponse), httpResponse);
                     return GetResponseInfo(httpResponse, httpResponse.GetResponseStream(), GetContentLength(httpResponse), httpResponse);
                 }
                 }
 
 
-                using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
+                using (var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false))
                 {
                 {
                     var httpResponse = (HttpWebResponse)response;
                     var httpResponse = (HttpWebResponse)response;
 
 
@@ -434,21 +434,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
 
 
                 throw exception;
                 throw exception;
             }
             }
-            catch (HttpRequestException ex)
-            {
-                _logger.ErrorException("Error getting response from " + options.Url, ex);
-
-                throw new HttpException(ex.Message, ex);
-            }
-            catch (WebException ex)
-            {
-                throw GetException(ex, options);
-            }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                _logger.ErrorException("Error getting response from " + options.Url, ex);
-
-                throw;
+                throw GetException(ex, options);
             }
             }
             finally
             finally
             {
             {
@@ -636,21 +624,10 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
                     return GetResponseInfo(httpResponse, tempFile, contentLength);
                     return GetResponseInfo(httpResponse, tempFile, contentLength);
                 }
                 }
             }
             }
-            catch (OperationCanceledException ex)
-            {
-                throw GetTempFileException(ex, options, tempFile);
-            }
-            catch (HttpRequestException ex)
-            {
-                throw GetTempFileException(ex, options, tempFile);
-            }
-            catch (WebException ex)
-            {
-                throw GetTempFileException(ex, options, tempFile);
-            }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                throw GetTempFileException(ex, options, tempFile);
+                DeleteTempFile(tempFile);
+                throw GetException(ex, options);
             }
             }
             finally
             finally
             {
             {
@@ -675,44 +652,25 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
 
 
         protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
         protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
 
-        /// <summary>
-        /// Handles the temp file exception.
-        /// </summary>
-        /// <param name="ex">The ex.</param>
-        /// <param name="options">The options.</param>
-        /// <param name="tempFile">The temp file.</param>
-        /// <returns>Task.</returns>
-        /// <exception cref="HttpException"></exception>
-        private Exception GetTempFileException(Exception ex, HttpRequestOptions options, string tempFile)
+        private Exception GetException(Exception ex, HttpRequestOptions options)
         {
         {
-            var operationCanceledException = ex as OperationCanceledException;
+            var webException = ex as WebException
+                ?? ex.InnerException as WebException;
 
 
-            if (operationCanceledException != null)
+            if (webException != null)
             {
             {
-                // Cleanup
-                DeleteTempFile(tempFile);
-
-                return GetCancellationException(options.Url, options.CancellationToken, operationCanceledException);
+                return GetException(webException, options);
             }
             }
 
 
-            _logger.ErrorException("Error getting response from " + options.Url, ex);
-
-            // Cleanup
-            DeleteTempFile(tempFile);
-
-            var httpRequestException = ex as HttpRequestException;
+            var operationCanceledException = ex as OperationCanceledException
+                ?? ex.InnerException as OperationCanceledException;
 
 
-            if (httpRequestException != null)
+            if (operationCanceledException != null)
             {
             {
-                return new HttpException(ex.Message, ex);
+                return GetCancellationException(options.Url, options.CancellationToken, operationCanceledException);
             }
             }
 
 
-            var webException = ex as WebException;
-
-            if (webException != null)
-            {
-                throw GetException(webException, options);
-            }
+            _logger.ErrorException("Error getting response from " + options.Url, ex);
 
 
             return ex;
             return ex;
         }
         }
@@ -843,5 +801,47 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
         {
         {
             return Post(url, postData, null, cancellationToken);
             return Post(url, postData, null, cancellationToken);
         }
         }
+
+        private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
+        {
+            var taskCompletion = new TaskCompletionSource<WebResponse>();
+
+            Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
+
+            ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, timeout, true);
+            asyncTask.ContinueWith(task =>
+            {
+                taskCompletion.TrySetResult(task.Result);
+
+            }, TaskContinuationOptions.NotOnFaulted);
+
+            // Handle errors
+            asyncTask.ContinueWith(task =>
+            {
+                if (task.Exception != null)
+                {
+                    taskCompletion.TrySetException(task.Exception);
+                }
+                else
+                {
+                    taskCompletion.TrySetException(new List<Exception>());
+                }
+
+            }, TaskContinuationOptions.OnlyOnFaulted);
+
+            return taskCompletion.Task;
+        }
+
+        private static void TimeoutCallback(object state, bool timedOut)
+        {
+            if (timedOut)
+            {
+                WebRequest request = (WebRequest)state;
+                if (state != null)
+                {
+                    request.Abort();
+                }
+            }
+        }
     }
     }
 }
 }

+ 4 - 0
MediaBrowser.Common/Net/HttpRequestOptions.cs

@@ -94,6 +94,8 @@ namespace MediaBrowser.Common.Net
         public CacheMode CacheMode { get; set; }
         public CacheMode CacheMode { get; set; }
         public TimeSpan CacheLength { get; set; }
         public TimeSpan CacheLength { get; set; }
 
 
+        public int TimeoutMs { get; set; }
+
         private string GetHeaderValue(string name)
         private string GetHeaderValue(string name)
         {
         {
             string value;
             string value;
@@ -115,6 +117,8 @@ namespace MediaBrowser.Common.Net
 
 
             LogRequest = true;
             LogRequest = true;
             CacheMode = CacheMode.None;
             CacheMode = CacheMode.None;
+
+            TimeoutMs = 20000;
         }
         }
 
 
         public void SetPostData(IDictionary<string,string> values)
         public void SetPostData(IDictionary<string,string> values)

+ 2 - 0
MediaBrowser.Controller/Connect/UserLinkResult.cs

@@ -4,5 +4,7 @@ namespace MediaBrowser.Controller.Connect
     public class UserLinkResult
     public class UserLinkResult
     {
     {
         public bool IsPending { get; set; }
         public bool IsPending { get; set; }
+        public bool IsNewUserInvitation { get; set; }
+        public string GuestDisplayName { get; set; }
     }
     }
 }
 }

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

@@ -1,8 +1,6 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
 namespace MediaBrowser.Controller.Dto
 namespace MediaBrowser.Controller.Dto
@@ -12,14 +10,6 @@ namespace MediaBrowser.Controller.Dto
     /// </summary>
     /// </summary>
     public interface IDtoService
     public interface IDtoService
     {
     {
-        /// <summary>
-        /// Gets the user dto.
-        /// </summary>
-        /// <param name="user">The user.</param>
-        /// <returns>UserDto.</returns>
-        [Obsolete]
-        UserDto GetUserDto(User user);
-
         /// <summary>
         /// <summary>
         /// Gets the dto id.
         /// Gets the dto id.
         /// </summary>
         /// </summary>

+ 3 - 1
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -226,7 +226,9 @@ namespace MediaBrowser.Controller.Entities.Audio
 
 
         public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
         public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
         {
         {
-            return inputItems.OfType<IHasArtist>().Where(i => i.HasArtist(Name)).Cast<BaseItem>();
+            return inputItems.OfType<IHasArtist>()
+                .Where(i => i.HasArtist(Name))
+                .Cast<BaseItem>();
         }
         }
     }
     }
 }
 }

+ 7 - 1
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -429,6 +429,12 @@ namespace MediaBrowser.Controller.Entities
             }
             }
         }
         }
 
 
+        [IgnoreDataMember]
+        public virtual BaseItem DisplayParent
+        {
+            get { return Parent; }
+        }
+
         /// <summary>
         /// <summary>
         /// When the item first debuted. For movies this could be premiere date, episodes would be first aired
         /// When the item first debuted. For movies this could be premiere date, episodes would be first aired
         /// </summary>
         /// </summary>
@@ -548,7 +554,7 @@ namespace MediaBrowser.Controller.Entities
                     return CustomRating;
                     return CustomRating;
                 }
                 }
 
 
-                var parent = Parent;
+                var parent = DisplayParent;
                 if (parent != null)
                 if (parent != null)
                 {
                 {
                     return parent.CustomRatingForComparison;
                     return parent.CustomRatingForComparison;

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

@@ -74,7 +74,8 @@ namespace MediaBrowser.Controller.Entities
             {
             {
                 FileInfo = new DirectoryInfo(path),
                 FileInfo = new DirectoryInfo(path),
                 Path = path,
                 Path = path,
-                Parent = Parent
+                Parent = Parent,
+                CollectionType = CollectionType
             };
             };
 
 
             // Gather child folder and files
             // Gather child folder and files

+ 36 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -736,7 +736,9 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         /// <returns>IEnumerable{BaseItem}.</returns>
         protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
         protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
         {
         {
-            return LibraryManager.ResolvePaths<BaseItem>(GetFileSystemChildren(directoryService), directoryService, this);
+            var collectionType = LibraryManager.FindCollectionType(this);
+
+            return LibraryManager.ResolvePaths<BaseItem>(GetFileSystemChildren(directoryService), directoryService, this, collectionType);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -745,7 +747,16 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         /// <returns>IEnumerable{BaseItem}.</returns>
         protected IEnumerable<BaseItem> GetCachedChildren()
         protected IEnumerable<BaseItem> GetCachedChildren()
         {
         {
-            return ItemRepository.GetChildren(Id).Select(RetrieveChild).Where(i => i != null);
+            var childrenItems = ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
+
+            //var children = ItemRepository.GetChildren(Id).Select(RetrieveChild).Where(i => i != null).ToList();
+
+            //if (children.Count != childrenItems.Count)
+            //{
+            //    var b = this;
+            //}
+
+            return childrenItems;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -770,6 +781,29 @@ namespace MediaBrowser.Controller.Entities
             return item;
             return item;
         }
         }
 
 
+        private BaseItem RetrieveChild(BaseItem child)
+        {
+            var item = LibraryManager.GetMemoryItemById(child.Id);
+
+            if (item != null)
+            {
+                if (item is IByReferenceItem)
+                {
+                    return LibraryManager.GetOrAddByReferenceItem(item);
+                }
+
+                item.Parent = this;
+            }
+            else
+            {
+                child.Parent = this;
+                LibraryManager.RegisterItem(child);
+                item = child;
+            }
+
+            return item;
+        }
+
         public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         {
         {
             var user = query.User;
             var user = query.User;

+ 13 - 27
MediaBrowser.Controller/Entities/MusicVideo.cs

@@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Entities
 {
 {
     public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
     public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
     {
     {
-        /// <summary>
-        /// Gets or sets the artist.
-        /// </summary>
-        /// <value>The artist.</value>
-        public string Artist { get; set; }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the album.
         /// Gets or sets the album.
         /// </summary>
         /// </summary>
@@ -35,43 +29,35 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The revenue.</value>
         /// <value>The revenue.</value>
         public double? Revenue { get; set; }
         public double? Revenue { get; set; }
         public List<string> ProductionLocations { get; set; }
         public List<string> ProductionLocations { get; set; }
+        public List<string> Artists { get; set; }
 
 
         public MusicVideo()
         public MusicVideo()
         {
         {
             ProductionLocations = new List<string>();
             ProductionLocations = new List<string>();
+            Artists = new List<string>();
         }
         }
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
-        public List<string> Artists
+        public List<string> AllArtists
         {
         {
             get
             get
             {
             {
-                var list = new List<string>();
-
-                if (!string.IsNullOrEmpty(Artist))
-                {
-                    list.Add(Artist);
-                }
-
-                return list;
-
+                return Artists;
             }
             }
         }
         }
 
 
-        [IgnoreDataMember]
-        public List<string> AllArtists
+        /// <summary>
+        /// TODO: Remove
+        /// </summary>
+        public string Artist
         {
         {
-            get
+            get { return Artists.FirstOrDefault(); }
+            set
             {
             {
-                var list = new List<string>();
-
-                if (!string.IsNullOrEmpty(Artist))
+                if (!string.IsNullOrEmpty(value) && !Artists.Contains(value, StringComparer.OrdinalIgnoreCase))
                 {
                 {
-                    list.Add(Artist);
+                    Artists.Add(value);
                 }
                 }
-
-                return list;
-
             }
             }
         }
         }
 
 
@@ -82,7 +68,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns><c>true</c> if the specified name has artist; otherwise, <c>false</c>.</returns>
         /// <returns><c>true</c> if the specified name has artist; otherwise, <c>false</c>.</returns>
         public bool HasArtist(string name)
         public bool HasArtist(string name)
         {
         {
-            return string.Equals(Artist, name, StringComparison.OrdinalIgnoreCase);
+            return AllArtists.Contains(name, StringComparer.OrdinalIgnoreCase);
         }
         }
         
         
         /// <summary>
         /// <summary>

+ 10 - 1
MediaBrowser.Controller/Entities/TV/Episode.cs

@@ -104,6 +104,15 @@ namespace MediaBrowser.Controller.Entities.TV
             }
             }
         }
         }
 
 
+        [IgnoreDataMember]
+        public override BaseItem DisplayParent
+        {
+            get
+            {
+                return Season ?? Parent;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>
@@ -153,7 +162,7 @@ namespace MediaBrowser.Controller.Entities.TV
                 // Episodes directly in series folder
                 // Episodes directly in series folder
                 if (season == null)
                 if (season == null)
                 {
                 {
-                    var series = FindParent<Series>();
+                    var series = Series;
 
 
                     if (ParentIndexNumber.HasValue)
                     if (ParentIndexNumber.HasValue)
                     {
                     {

+ 6 - 0
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -44,6 +44,12 @@ namespace MediaBrowser.Controller.Entities.TV
             }
             }
         }
         }
 
 
+        [IgnoreDataMember]
+        public override BaseItem DisplayParent
+        {
+            get { return Series ?? Parent; }
+        }
+
         /// <summary>
         /// <summary>
         /// We want to group into our Series
         /// We want to group into our Series
         /// </summary>
         /// </summary>

+ 11 - 19
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -17,30 +17,14 @@ namespace MediaBrowser.Controller.Library
     /// </summary>
     /// </summary>
     public interface ILibraryManager
     public interface ILibraryManager
     {
     {
-        /// <summary>
-        /// Resolves the item.
-        /// </summary>
-        /// <param name="args">The args.</param>
-        /// <returns>BaseItem.</returns>
-        BaseItem ResolveItem(ItemResolveArgs args);
-
-        /// <summary>
-        /// Resolves a path into a BaseItem
-        /// </summary>
-        /// <param name="fileInfo">The file info.</param>
-        /// <param name="directoryService">The directory service.</param>
-        /// <param name="parent">The parent.</param>
-        /// <returns>BaseItem.</returns>
-        /// <exception cref="System.ArgumentNullException"></exception>
-        BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null);
-
         /// <summary>
         /// <summary>
         /// Resolves the path.
         /// Resolves the path.
         /// </summary>
         /// </summary>
         /// <param name="fileInfo">The file information.</param>
         /// <param name="fileInfo">The file information.</param>
         /// <param name="parent">The parent.</param>
         /// <param name="parent">The parent.</param>
+        /// <param name="collectionType">Type of the collection.</param>
         /// <returns>BaseItem.</returns>
         /// <returns>BaseItem.</returns>
-        BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null);
+        BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null, string collectionType = null);
 
 
         /// <summary>
         /// <summary>
         /// Resolves a set of files into a list of BaseItem
         /// Resolves a set of files into a list of BaseItem
@@ -49,8 +33,9 @@ namespace MediaBrowser.Controller.Library
         /// <param name="files">The files.</param>
         /// <param name="files">The files.</param>
         /// <param name="directoryService">The directory service.</param>
         /// <param name="directoryService">The directory service.</param>
         /// <param name="parent">The parent.</param>
         /// <param name="parent">The parent.</param>
+        /// <param name="collectionType">Type of the collection.</param>
         /// <returns>List{``0}.</returns>
         /// <returns>List{``0}.</returns>
-        List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent)
+        List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent, string collectionType = null)
             where T : BaseItem;
             where T : BaseItem;
 
 
         /// <summary>
         /// <summary>
@@ -151,6 +136,13 @@ namespace MediaBrowser.Controller.Library
         /// <returns>BaseItem.</returns>
         /// <returns>BaseItem.</returns>
         BaseItem GetItemById(Guid id);
         BaseItem GetItemById(Guid id);
 
 
+        /// <summary>
+        /// Gets the memory item by identifier.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <returns>BaseItem.</returns>
+        BaseItem GetMemoryItemById(Guid id);
+        
         /// <summary>
         /// <summary>
         /// Gets the intros.
         /// Gets the intros.
         /// </summary>
         /// </summary>

+ 0 - 1
MediaBrowser.Controller/Library/IMetadataSaver.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
 using System.Threading;
 using System.Threading;
 
 
 namespace MediaBrowser.Controller.Library
 namespace MediaBrowser.Controller.Library

+ 7 - 25
MediaBrowser.Controller/Library/ItemResolveArgs.cs

@@ -230,29 +230,18 @@ namespace MediaBrowser.Controller.Library
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Gets the name of the meta file by.
+        /// Determines whether [contains meta file by name] [the specified name].
         /// </summary>
         /// </summary>
         /// <param name="name">The name.</param>
         /// <param name="name">The name.</param>
-        /// <returns>FileSystemInfo.</returns>
-        /// <exception cref="System.ArgumentNullException"></exception>
-        public FileSystemInfo GetMetaFileByName(string name)
+        /// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns>
+        public bool ContainsMetaFileByName(string name)
         {
         {
             if (string.IsNullOrEmpty(name))
             if (string.IsNullOrEmpty(name))
             {
             {
                 throw new ArgumentNullException();
                 throw new ArgumentNullException();
             }
             }
 
 
-            return GetFileSystemEntryByName(name);
-        }
-
-        /// <summary>
-        /// Determines whether [contains meta file by name] [the specified name].
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns>
-        public bool ContainsMetaFileByName(string name)
-        {
-            return GetMetaFileByName(name) != null;
+            return GetFileSystemEntryByName(name) != null;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -265,20 +254,13 @@ namespace MediaBrowser.Controller.Library
             return GetFileSystemEntryByName(name) != null;
             return GetFileSystemEntryByName(name) != null;
         }
         }
 
 
-        private bool _collectionTypeDiscovered;
-        private string _collectionType;
-
         public string GetCollectionType()
         public string GetCollectionType()
         {
         {
-            if (!_collectionTypeDiscovered)
-            {
-                _collectionType = Parent == null ? null : _libraryManager.FindCollectionType(Parent);
-                _collectionTypeDiscovered = true;
-            }
-
-            return _collectionType;
+            return CollectionType;
         }
         }
 
 
+        public string CollectionType { get; set; }
+
         #region Equality Overrides
         #region Equality Overrides
 
 
         /// <summary>
         /// <summary>

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

@@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.Library
                 {
                 {
                     if (IsSeasonFolder(child.FullName, directoryService, fileSystem))
                     if (IsSeasonFolder(child.FullName, directoryService, fileSystem))
                     {
                     {
-                        logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
+                        //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
                         return true;
                         return true;
                     }
                     }
 
 

+ 9 - 2
MediaBrowser.Controller/Persistence/IItemRepository.cs

@@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Persistence
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         Task DeleteItem(Guid id, CancellationToken cancellationToken);
         Task DeleteItem(Guid id, CancellationToken cancellationToken);
-        
+
         /// <summary>
         /// <summary>
         /// Gets the critic reviews.
         /// Gets the critic reviews.
         /// </summary>
         /// </summary>
@@ -41,6 +41,13 @@ namespace MediaBrowser.Controller.Persistence
         /// <returns>Task{IEnumerable{ItemReview}}.</returns>
         /// <returns>Task{IEnumerable{ItemReview}}.</returns>
         IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
         IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
 
 
+        /// <summary>
+        /// Gets the children items.
+        /// </summary>
+        /// <param name="parentId">The parent identifier.</param>
+        /// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
+        IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
+
         /// <summary>
         /// <summary>
         /// Saves the critic reviews.
         /// Saves the critic reviews.
         /// </summary>
         /// </summary>
@@ -101,7 +108,7 @@ namespace MediaBrowser.Controller.Persistence
         /// <param name="type">The type.</param>
         /// <param name="type">The type.</param>
         /// <returns>IEnumerable{Guid}.</returns>
         /// <returns>IEnumerable{Guid}.</returns>
         IEnumerable<BaseItem> GetItemsOfType(Type type);
         IEnumerable<BaseItem> GetItemsOfType(Type type);
-        
+
         /// <summary>
         /// <summary>
         /// Saves the children.
         /// Saves the children.
         /// </summary>
         /// </summary>

+ 0 - 4
MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs

@@ -14,10 +14,6 @@ namespace MediaBrowser.Controller.Providers
 
 
         public MetadataRefreshMode MetadataRefreshMode { get; set; }
         public MetadataRefreshMode MetadataRefreshMode { get; set; }
 
 
-        /// <summary>
-        /// TODO: deprecate. Keeping this for now, for api compatibility
-        /// </summary>
-        [Obsolete]
         public bool ForceSave { get; set; }
         public bool ForceSave { get; set; }
 
 
         public MetadataRefreshOptions()
         public MetadataRefreshOptions()

+ 1 - 1
MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs

@@ -246,7 +246,7 @@ namespace MediaBrowser.Controller.Resolvers
 
 
             if (config.UseFileCreationTimeForDateAdded)
             if (config.UseFileCreationTimeForDateAdded)
             {
             {
-                item.DateModified = fileSystem.GetCreationTimeUtc(info);
+                item.DateCreated = fileSystem.GetCreationTimeUtc(info);
             }
             }
             else
             else
             {
             {

+ 6 - 0
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -80,6 +80,12 @@ namespace MediaBrowser.Controller.Session
         /// <value>The last activity date.</value>
         /// <value>The last activity date.</value>
         public DateTime LastActivityDate { get; set; }
         public DateTime LastActivityDate { get; set; }
 
 
+        /// <summary>
+        /// Gets or sets the last playback check in.
+        /// </summary>
+        /// <value>The last playback check in.</value>
+        public DateTime LastPlaybackCheckIn { get; set; }
+
         /// <summary>
         /// <summary>
         /// Gets or sets the name of the device.
         /// Gets or sets the name of the device.
         /// </summary>
         /// </summary>

+ 110 - 33
MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Extensions;
+using System.Linq;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Dlna.Didl;
 using MediaBrowser.Dlna.Didl;
@@ -85,7 +87,9 @@ namespace MediaBrowser.Dlna.ContentDirectory
         {
         {
             var id = sparams["ObjectID"];
             var id = sparams["ObjectID"];
 
 
-            var item = GetItemFromObjectId(id, user);
+            var serverItem = GetItemFromObjectId(id, user);
+
+            var item = serverItem.Item;
 
 
             var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
             var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
 
 
@@ -173,49 +177,48 @@ namespace MediaBrowser.Dlna.ContentDirectory
             //didl.SetAttribute("xmlns:sec", NS_SEC);
             //didl.SetAttribute("xmlns:sec", NS_SEC);
             result.AppendChild(didl);
             result.AppendChild(didl);
 
 
-            var item = GetItemFromObjectId(id, user);
+            var serverItem = GetItemFromObjectId(id, user);
+            var item = serverItem.Item;
 
 
             var totalCount = 0;
             var totalCount = 0;
 
 
             if (string.Equals(flag, "BrowseMetadata"))
             if (string.Equals(flag, "BrowseMetadata"))
             {
             {
-                var folder = item as Folder;
-
-                if (folder == null)
+                if (item.IsFolder || serverItem.StubType.HasValue)
                 {
                 {
-                    result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, item, null, deviceId, filter));
+                    var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false));
+                    totalCount = childrenResult.TotalRecordCount;
+
+                    result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, item, serverItem.StubType, null, totalCount, filter, id));
                 }
                 }
                 else
                 else
                 {
                 {
-                    var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
-                    totalCount = childrenResult.TotalRecordCount;
-
-                    result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter, id));
+                    result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, item, null, null, deviceId, filter));
                 }
                 }
+
                 provided++;
                 provided++;
             }
             }
             else
             else
             {
             {
-                var folder = (Folder)item;
-
-                var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
+                var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false));
                 totalCount = childrenResult.TotalRecordCount;
                 totalCount = childrenResult.TotalRecordCount;
 
 
                 provided = childrenResult.Items.Length;
                 provided = childrenResult.Items.Length;
 
 
                 foreach (var i in childrenResult.Items)
                 foreach (var i in childrenResult.Items)
                 {
                 {
-                    if (i.IsFolder)
+                    var displayStubType = GetDisplayStubType(i, serverItem.Item);
+
+                    if (i.IsFolder || displayStubType.HasValue)
                     {
                     {
-                        var f = (Folder)i;
-                        var childCount = (await GetUserItems(f, user, sortCriteria, null, 0).ConfigureAwait(false))
+                        var childCount = (await GetUserItems(i, displayStubType, user, sortCriteria, null, 0).ConfigureAwait(false))
                             .TotalRecordCount;
                             .TotalRecordCount;
 
 
-                        result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
+                        result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, i, displayStubType, item, childCount, filter));
                     }
                     }
                     else
                     else
                     {
                     {
-                        result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, folder, deviceId, filter));
+                        result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, item, serverItem.StubType, deviceId, filter));
                     }
                     }
                 }
                 }
             }
             }
@@ -231,6 +234,24 @@ namespace MediaBrowser.Dlna.ContentDirectory
             };
             };
         }
         }
 
 
+        private StubType? GetDisplayStubType(BaseItem item, BaseItem context)
+        {
+            if (context == null || context.IsFolder)
+            {
+                var movie = item as Movie;
+                if (movie != null)
+                {
+                    if (movie.LocalTrailerIds.Count > 0 ||
+                        movie.SpecialFeatureIds.Count > 0)
+                    {
+                        return StubType.Folder;
+                    }
+                }
+            }
+
+            return null;
+        }
+
         private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
         private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
         {
         {
             var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
             var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
@@ -269,9 +290,11 @@ namespace MediaBrowser.Dlna.ContentDirectory
 
 
             result.AppendChild(didl);
             result.AppendChild(didl);
 
 
-            var folder = (Folder)GetItemFromObjectId(sparams["ContainerID"], user);
+            var serverItem = GetItemFromObjectId(sparams["ContainerID"], user);
+
+            var item = serverItem.Item;
 
 
-            var childrenResult = (await GetChildrenSorted(folder, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
+            var childrenResult = (await GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
 
 
             var totalCount = childrenResult.TotalRecordCount;
             var totalCount = childrenResult.TotalRecordCount;
 
 
@@ -281,15 +304,14 @@ namespace MediaBrowser.Dlna.ContentDirectory
             {
             {
                 if (i.IsFolder)
                 if (i.IsFolder)
                 {
                 {
-                    var f = (Folder)i;
-                    var childCount = (await GetChildrenSorted(f, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
+                    var childCount = (await GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
                         .TotalRecordCount;
                         .TotalRecordCount;
 
 
-                    result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
+                    result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, i, null, item, childCount, filter));
                 }
                 }
                 else
                 else
                 {
                 {
-                    result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, folder, deviceId, filter));
+                    result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, item, serverItem.StubType, deviceId, filter));
                 }
                 }
             }
             }
 
 
@@ -304,8 +326,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
             };
             };
         }
         }
 
 
-        private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
+        private async Task<QueryResult<BaseItem>> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
         {
         {
+            var folder = (Folder)item;
+
             var sortOrders = new List<string>();
             var sortOrders = new List<string>();
             if (!folder.IsPreSorted)
             if (!folder.IsPreSorted)
             {
             {
@@ -340,7 +364,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
                 //items = items.OfType<MusicAlbum>();
                 //items = items.OfType<MusicAlbum>();
                 isFolder = true;
                 isFolder = true;
             }
             }
-            
+
             return await folder.GetItems(new InternalItemsQuery
             return await folder.GetItems(new InternalItemsQuery
             {
             {
                 Limit = limit,
                 Limit = limit,
@@ -356,8 +380,20 @@ namespace MediaBrowser.Dlna.ContentDirectory
             }).ConfigureAwait(false);
             }).ConfigureAwait(false);
         }
         }
 
 
-        private async Task<QueryResult<BaseItem>> GetUserItems(Folder folder, User user, SortCriteria sort, int? startIndex, int? limit)
+        private async Task<QueryResult<BaseItem>> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit)
         {
         {
+            if (stubType.HasValue)
+            {
+                var movie = item as Movie;
+
+                if (movie != null)
+                {
+                    return await GetMovieItems(movie).ConfigureAwait(false);
+                }
+            }
+
+            var folder = (Folder)item;
+
             var sortOrders = new List<string>();
             var sortOrders = new List<string>();
             if (!folder.IsPreSorted)
             if (!folder.IsPreSorted)
             {
             {
@@ -376,6 +412,23 @@ namespace MediaBrowser.Dlna.ContentDirectory
             }).ConfigureAwait(false);
             }).ConfigureAwait(false);
         }
         }
 
 
+        private Task<QueryResult<BaseItem>> GetMovieItems(Movie item)
+        {
+            var list = new List<BaseItem>();
+
+            list.Add(item);
+
+            list.AddRange(item.LocalTrailerIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
+            list.AddRange(item.SpecialFeatureIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
+            list.AddRange(item.ThemeVideoIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
+
+            return Task.FromResult(new QueryResult<BaseItem>
+            {
+                Items = list.ToArray(),
+                TotalRecordCount = list.Count
+            });
+        }
+
         private bool FilterUnsupportedContent(BaseItem i, User user)
         private bool FilterUnsupportedContent(BaseItem i, User user)
         {
         {
             // Unplayable
             // Unplayable
@@ -399,26 +452,50 @@ namespace MediaBrowser.Dlna.ContentDirectory
             return true;
             return true;
         }
         }
 
 
-        private BaseItem GetItemFromObjectId(string id, User user)
+        private ServerItem GetItemFromObjectId(string id, User user)
         {
         {
             return DidlBuilder.IsIdRoot(id)
             return DidlBuilder.IsIdRoot(id)
 
 
-                 ? user.RootFolder
+                 ? new ServerItem { Item = user.RootFolder }
                  : ParseItemId(id, user);
                  : ParseItemId(id, user);
         }
         }
 
 
-        private BaseItem ParseItemId(string id, User user)
+        private ServerItem ParseItemId(string id, User user)
         {
         {
             Guid itemId;
             Guid itemId;
+            StubType? stubType = null;
+
+            if (id.StartsWith("folder_", StringComparison.OrdinalIgnoreCase))
+            {
+                stubType = StubType.Folder;
+                id = id.Split(new[] { '_' }, 2)[1];
+            }
 
 
             if (Guid.TryParse(id, out itemId))
             if (Guid.TryParse(id, out itemId))
             {
             {
-                return _libraryManager.GetItemById(itemId);
+                var item = _libraryManager.GetItemById(itemId);
+
+                return new ServerItem
+                {
+                    Item = item,
+                    StubType = stubType
+                };
             }
             }
 
 
             Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
             Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
 
 
-            return user.RootFolder;
+            return new ServerItem { Item = user.RootFolder };
         }
         }
     }
     }
+
+    internal class ServerItem
+    {
+        public BaseItem Item { get; set; }
+        public StubType? StubType { get; set; }
+    }
+
+    public enum StubType
+    {
+        Folder = 0
+    }
 }
 }

+ 84 - 43
MediaBrowser.Dlna/Didl/DidlBuilder.cs

@@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Playlists;
 using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Dlna.ContentDirectory;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -63,25 +64,35 @@ namespace MediaBrowser.Dlna.Didl
 
 
             result.AppendChild(didl);
             result.AppendChild(didl);
 
 
-            result.DocumentElement.AppendChild(GetItemElement(result, item, context, deviceId, filter, streamInfo));
+            result.DocumentElement.AppendChild(GetItemElement(result, item, context, null, deviceId, filter, streamInfo));
 
 
             return result.DocumentElement.OuterXml;
             return result.DocumentElement.OuterXml;
         }
         }
 
 
-        public XmlElement GetItemElement(XmlDocument doc, BaseItem item, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo = null)
+        public XmlElement GetItemElement(XmlDocument doc, BaseItem item, BaseItem context, StubType? contextStubType, string deviceId, Filter filter, StreamInfo streamInfo = null)
         {
         {
+            var clientId = GetClientId(item, null);
+
             var element = doc.CreateElement(string.Empty, "item", NS_DIDL);
             var element = doc.CreateElement(string.Empty, "item", NS_DIDL);
             element.SetAttribute("restricted", "1");
             element.SetAttribute("restricted", "1");
-            element.SetAttribute("id", item.Id.ToString("N"));
+            element.SetAttribute("id", clientId);
 
 
-            if (item.Parent != null)
+            if (context != null)
+            {
+                element.SetAttribute("parentID", GetClientId(context, contextStubType));
+            }
+            else
             {
             {
-                element.SetAttribute("parentID", item.Parent.Id.ToString("N"));
+                var parent = item.DisplayParent;
+                if (parent != null)
+                {
+                    element.SetAttribute("parentID", GetClientId(parent, null));
+                }
             }
             }
 
 
             //AddBookmarkInfo(item, user, element);
             //AddBookmarkInfo(item, user, element);
 
 
-            AddGeneralProperties(item, context, element, filter);
+            AddGeneralProperties(item, null, context, element, filter);
 
 
             // refID?
             // refID?
             // storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
             // storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
@@ -111,14 +122,14 @@ namespace MediaBrowser.Dlna.Didl
             {
             {
                 var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();
                 var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();
 
 
-               streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
-               {
-                   ItemId = video.Id.ToString("N"),
-                   MediaSources = sources,
-                   Profile = _profile,
-                   DeviceId = deviceId,
-                   MaxBitrate = _profile.MaxStreamingBitrate
-               });
+                streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
+                {
+                    ItemId = GetClientId(video),
+                    MediaSources = sources,
+                    Profile = _profile,
+                    DeviceId = deviceId,
+                    MaxBitrate = _profile.MaxStreamingBitrate
+                });
             }
             }
 
 
             var targetWidth = streamInfo.TargetWidth;
             var targetWidth = streamInfo.TargetWidth;
@@ -142,6 +153,7 @@ namespace MediaBrowser.Dlna.Didl
                 streamInfo.TargetPacketLength,
                 streamInfo.TargetPacketLength,
                 streamInfo.TranscodeSeekInfo,
                 streamInfo.TranscodeSeekInfo,
                 streamInfo.IsTargetAnamorphic,
                 streamInfo.IsTargetAnamorphic,
+                streamInfo.IsTargetCabac,
                 streamInfo.TargetRefFrames);
                 streamInfo.TargetRefFrames);
 
 
             foreach (var contentFeature in contentFeatureList)
             foreach (var contentFeature in contentFeatureList)
@@ -263,6 +275,7 @@ namespace MediaBrowser.Dlna.Didl
                 streamInfo.TargetPacketLength,
                 streamInfo.TargetPacketLength,
                 streamInfo.TargetTimestamp,
                 streamInfo.TargetTimestamp,
                 streamInfo.IsTargetAnamorphic,
                 streamInfo.IsTargetAnamorphic,
+                streamInfo.IsTargetCabac,
                 streamInfo.TargetRefFrames);
                 streamInfo.TargetRefFrames);
 
 
             var filename = url.Substring(0, url.IndexOf('?'));
             var filename = url.Substring(0, url.IndexOf('?'));
@@ -311,7 +324,7 @@ namespace MediaBrowser.Dlna.Didl
 
 
             return item.Name;
             return item.Name;
         }
         }
-        
+
         private void AddAudioResource(XmlElement container, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
         private void AddAudioResource(XmlElement container, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
         {
         {
             var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
             var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
@@ -322,7 +335,7 @@ namespace MediaBrowser.Dlna.Didl
 
 
                 streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
                 streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
                {
                {
-                   ItemId = audio.Id.ToString("N"),
+                   ItemId = GetClientId(audio),
                    MediaSources = sources,
                    MediaSources = sources,
                    Profile = _profile,
                    Profile = _profile,
                    DeviceId = deviceId
                    DeviceId = deviceId
@@ -403,8 +416,8 @@ namespace MediaBrowser.Dlna.Didl
 
 
         public static bool IsIdRoot(string id)
         public static bool IsIdRoot(string id)
         {
         {
-            if (string.IsNullOrWhiteSpace(id) || 
-                
+            if (string.IsNullOrWhiteSpace(id) ||
+
                 string.Equals(id, "0", StringComparison.OrdinalIgnoreCase)
                 string.Equals(id, "0", StringComparison.OrdinalIgnoreCase)
 
 
                 // Samsung sometimes uses 1 as root
                 // Samsung sometimes uses 1 as root
@@ -416,13 +429,15 @@ namespace MediaBrowser.Dlna.Didl
             return false;
             return false;
         }
         }
 
 
-        public XmlElement GetFolderElement(XmlDocument doc, BaseItem folder, int childCount, Filter filter, string requestedId = null)
+        public XmlElement GetFolderElement(XmlDocument doc, BaseItem folder, StubType? stubType, BaseItem context, int childCount, Filter filter, string requestedId = null)
         {
         {
             var container = doc.CreateElement(string.Empty, "container", NS_DIDL);
             var container = doc.CreateElement(string.Empty, "container", NS_DIDL);
             container.SetAttribute("restricted", "0");
             container.SetAttribute("restricted", "0");
             container.SetAttribute("searchable", "1");
             container.SetAttribute("searchable", "1");
             container.SetAttribute("childCount", childCount.ToString(_usCulture));
             container.SetAttribute("childCount", childCount.ToString(_usCulture));
 
 
+            var clientId = GetClientId(folder, stubType);
+
             if (string.Equals(requestedId, "0"))
             if (string.Equals(requestedId, "0"))
             {
             {
                 container.SetAttribute("id", "0");
                 container.SetAttribute("id", "0");
@@ -430,20 +445,20 @@ namespace MediaBrowser.Dlna.Didl
             }
             }
             else
             else
             {
             {
-                container.SetAttribute("id", folder.Id.ToString("N"));
+                container.SetAttribute("id", clientId);
 
 
-                var parent = folder.Parent;
+                var parent = context ?? folder.DisplayParent;
                 if (parent == null)
                 if (parent == null)
                 {
                 {
                     container.SetAttribute("parentID", "0");
                     container.SetAttribute("parentID", "0");
                 }
                 }
                 else
                 else
                 {
                 {
-                    container.SetAttribute("parentID", parent.Id.ToString("N"));
+                    container.SetAttribute("parentID", GetClientId(parent, null));
                 }
                 }
             }
             }
 
 
-            AddCommonFields(folder, null, container, filter);
+            AddCommonFields(folder, stubType, null, container, filter);
 
 
             AddCover(folder, container);
             AddCover(folder, container);
 
 
@@ -466,10 +481,11 @@ namespace MediaBrowser.Dlna.Didl
         /// Adds fields used by both items and folders
         /// Adds fields used by both items and folders
         /// </summary>
         /// </summary>
         /// <param name="item">The item.</param>
         /// <param name="item">The item.</param>
+        /// <param name="itemStubType">Type of the item stub.</param>
         /// <param name="context">The context.</param>
         /// <param name="context">The context.</param>
         /// <param name="element">The element.</param>
         /// <param name="element">The element.</param>
         /// <param name="filter">The filter.</param>
         /// <param name="filter">The filter.</param>
-        private void AddCommonFields(BaseItem item, BaseItem context, XmlElement element, Filter filter)
+        private void AddCommonFields(BaseItem item, StubType? itemStubType, BaseItem context, XmlElement element, Filter filter)
         {
         {
             // Don't filter on dc:title because not all devices will include it in the filter
             // Don't filter on dc:title because not all devices will include it in the filter
             // MediaMonkey for example won't display content without a title
             // MediaMonkey for example won't display content without a title
@@ -478,7 +494,7 @@ namespace MediaBrowser.Dlna.Didl
                 AddValue(element, "dc", "title", GetDisplayName(item, context), NS_DC);
                 AddValue(element, "dc", "title", GetDisplayName(item, context), NS_DC);
             }
             }
 
 
-            element.AppendChild(CreateObjectClass(element.OwnerDocument, item));
+            element.AppendChild(CreateObjectClass(element.OwnerDocument, item, itemStubType));
 
 
             if (filter.Contains("dc:date"))
             if (filter.Contains("dc:date"))
             {
             {
@@ -539,14 +555,14 @@ namespace MediaBrowser.Dlna.Didl
             AddPeople(item, element);
             AddPeople(item, element);
         }
         }
 
 
-        private XmlElement CreateObjectClass(XmlDocument result, BaseItem item)
+        private XmlElement CreateObjectClass(XmlDocument result, BaseItem item, StubType? stubType)
         {
         {
             // More types here
             // More types here
             // http://oss.linn.co.uk/repos/Public/LibUpnpCil/DidlLite/UpnpAv/Test/TestDidlLite.cs
             // http://oss.linn.co.uk/repos/Public/LibUpnpCil/DidlLite/UpnpAv/Test/TestDidlLite.cs
 
 
             var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
             var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
 
 
-            if (item.IsFolder)
+            if (item.IsFolder || stubType.HasValue)
             {
             {
                 string classType = null;
                 string classType = null;
 
 
@@ -560,7 +576,7 @@ namespace MediaBrowser.Dlna.Didl
                     {
                     {
                         classType = "object.container.person.musicArtist";
                         classType = "object.container.person.musicArtist";
                     }
                     }
-                    else if (item is Series || item is Season || item is BoxSet)
+                    else if (item is Series || item is Season || item is BoxSet || item is Video)
                     {
                     {
                         classType = "object.container.album.videoAlbum";
                         classType = "object.container.album.videoAlbum";
                     }
                     }
@@ -628,9 +644,9 @@ namespace MediaBrowser.Dlna.Didl
             }
             }
         }
         }
 
 
-        private void AddGeneralProperties(BaseItem item, BaseItem context, XmlElement element, Filter filter)
+        private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlElement element, Filter filter)
         {
         {
-            AddCommonFields(item, context, element, filter);
+            AddCommonFields(item, itemStubType, context, element, filter);
 
 
             var audio = item as Audio;
             var audio = item as Audio;
 
 
@@ -671,10 +687,10 @@ namespace MediaBrowser.Dlna.Didl
 
 
             if (musicVideo != null)
             if (musicVideo != null)
             {
             {
-                if (!string.IsNullOrEmpty(musicVideo.Artist))
+                foreach (var artist in musicVideo.Artists)
                 {
                 {
-                    AddValue(element, "upnp", "artist", musicVideo.Artist, NS_UPNP);
-                    AddAlbumArtist(element, musicVideo.Artist);
+                    AddValue(element, "upnp", "artist", artist, NS_UPNP);
+                    AddAlbumArtist(element, artist);
                 }
                 }
 
 
                 if (!string.IsNullOrEmpty(musicVideo.Album))
                 if (!string.IsNullOrEmpty(musicVideo.Album))
@@ -773,20 +789,26 @@ namespace MediaBrowser.Dlna.Didl
                 }
                 }
             }
             }
 
 
-            AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG");
-            AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG");
-            AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED");
-            AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM");
+            var imageLimit = _profile.DidlAlbumArtLimit ?? 100;
+
             AddImageResElement(item, element, 160, 160, playbackPercentage, "jpg", "JPEG_TN");
             AddImageResElement(item, element, 160, 160, playbackPercentage, "jpg", "JPEG_TN");
-            AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN");
+
+            if (imageLimit > 1)
+            {
+                AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG");
+                AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED");
+                AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM");
+                AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG");
+                AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN");
+            }
         }
         }
 
 
-        private void AddImageResElement(BaseItem item, 
-            XmlElement element, 
-            int maxWidth, 
-            int maxHeight, 
+        private void AddImageResElement(BaseItem item,
+            XmlElement element,
+            int maxWidth,
+            int maxHeight,
             int playbackPercentage,
             int playbackPercentage,
-            string format, 
+            string format,
             string org_Pn)
             string org_Pn)
         {
         {
             var imageInfo = GetImageInfo(item);
             var imageInfo = GetImageInfo(item);
@@ -920,6 +942,25 @@ namespace MediaBrowser.Dlna.Didl
             internal int? Height;
             internal int? Height;
         }
         }
 
 
+        public static string GetClientId(BaseItem item, StubType? stubType)
+        {
+            var id = item.Id.ToString("N");
+
+            if (stubType.HasValue)
+            {
+                id = stubType.Value.ToString().ToLower() + "_" + id;
+            }
+
+            return id;
+        }
+
+        public static string GetClientId(IHasMediaSources item)
+        {
+            var id = item.Id.ToString("N");
+
+            return id;
+        }
+
         private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, string format)
         private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, string format)
         {
         {
             var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}",
             var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}",

+ 63 - 40
MediaBrowser.Dlna/DlnaManager.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Dlna.Profiles;
 using MediaBrowser.Dlna.Profiles;
 using MediaBrowser.Dlna.Server;
 using MediaBrowser.Dlna.Server;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
@@ -37,8 +38,6 @@ namespace MediaBrowser.Dlna
             _appPaths = appPaths;
             _appPaths = appPaths;
             _logger = logger;
             _logger = logger;
             _jsonSerializer = jsonSerializer;
             _jsonSerializer = jsonSerializer;
-
-            //DumpProfiles();
         }
         }
 
 
         public IEnumerable<DeviceProfile> GetProfiles()
         public IEnumerable<DeviceProfile> GetProfiles()
@@ -55,44 +54,6 @@ namespace MediaBrowser.Dlna
             return list;
             return list;
         }
         }
 
 
-        private void DumpProfiles()
-        {
-            var list = new List<DeviceProfile>
-            {
-                new SamsungSmartTvProfile(),
-                new Xbox360Profile(),
-                new XboxOneProfile(),
-                new SonyPs3Profile(),
-                new SonyBravia2010Profile(),
-                new SonyBravia2011Profile(),
-                new SonyBravia2012Profile(),
-                new SonyBravia2013Profile(),
-                new SonyBlurayPlayer2013Profile(),
-                new SonyBlurayPlayerProfile(),
-                new PanasonicVieraProfile(),
-                new WdtvLiveProfile(),
-                new DenonAvrProfile(),
-                new LinksysDMA2100Profile(),
-                new LgTvProfile(),
-                new Foobar2000Profile(),
-                new MediaMonkeyProfile(),
-                new Windows81Profile(),
-                //new WindowsMediaCenterProfile(),
-                new WindowsPhoneProfile(),
-                new AndroidProfile(true, true, new[]{"baseline", "constrained baseline"}),
-                new DirectTvProfile(),
-                new DishHopperJoeyProfile(),
-                new DefaultProfile()
-            };
-
-            foreach (var item in list)
-            {
-                var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
-
-                _xmlSerializer.SerializeToFile(item, path);
-            }
-        }
-
         private bool _extracted;
         private bool _extracted;
         private readonly object _syncLock = new object();
         private readonly object _syncLock = new object();
         private void ExtractProfilesIfNeeded()
         private void ExtractProfilesIfNeeded()
@@ -521,4 +482,66 @@ namespace MediaBrowser.Dlna
             };
             };
         }
         }
     }
     }
+
+    class DlnaProfileEntryPoint : IServerEntryPoint
+    {
+        private readonly IApplicationPaths _appPaths;
+        private readonly IXmlSerializer _xmlSerializer;
+        private readonly IFileSystem _fileSystem;
+
+        public DlnaProfileEntryPoint(IApplicationPaths appPaths, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
+        {
+            _appPaths = appPaths;
+            _xmlSerializer = xmlSerializer;
+            _fileSystem = fileSystem;
+        }
+
+        public void Run()
+        {
+            //DumpProfiles();
+        }
+
+        private void DumpProfiles()
+        {
+            var list = new List<DeviceProfile>
+            {
+                new SamsungSmartTvProfile(),
+                new Xbox360Profile(),
+                new XboxOneProfile(),
+                new SonyPs3Profile(),
+                new SonyBravia2010Profile(),
+                new SonyBravia2011Profile(),
+                new SonyBravia2012Profile(),
+                new SonyBravia2013Profile(),
+                new SonyBlurayPlayer2013Profile(),
+                new SonyBlurayPlayerProfile(),
+                new PanasonicVieraProfile(),
+                new WdtvLiveProfile(),
+                new DenonAvrProfile(),
+                new LinksysDMA2100Profile(),
+                new LgTvProfile(),
+                new Foobar2000Profile(),
+                new MediaMonkeyProfile(),
+                new Windows81Profile(),
+                //new WindowsMediaCenterProfile(),
+                new WindowsPhoneProfile(),
+                new AndroidProfile(),
+                new DirectTvProfile(),
+                new DishHopperJoeyProfile(),
+                new DefaultProfile(),
+                new PopcornHourProfile()
+            };
+
+            foreach (var item in list)
+            {
+                var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
+
+                _xmlSerializer.SerializeToFile(item, path);
+            }
+        }
+
+        public void Dispose()
+        {
+        }
+    }
 }
 }

+ 4 - 0
MediaBrowser.Dlna/MediaBrowser.Dlna.csproj

@@ -75,6 +75,7 @@
     <Compile Include="PlayTo\PlayToController.cs" />
     <Compile Include="PlayTo\PlayToController.cs" />
     <Compile Include="Profiles\DirectTvProfile.cs" />
     <Compile Include="Profiles\DirectTvProfile.cs" />
     <Compile Include="Profiles\DishHopperJoeyProfile.cs" />
     <Compile Include="Profiles\DishHopperJoeyProfile.cs" />
+    <Compile Include="Profiles\PopcornHourProfile.cs" />
     <Compile Include="Ssdp\DeviceDiscoveryInfo.cs" />
     <Compile Include="Ssdp\DeviceDiscoveryInfo.cs" />
     <Compile Include="Ssdp\Extensions.cs" />
     <Compile Include="Ssdp\Extensions.cs" />
     <Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
     <Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
@@ -194,6 +195,9 @@
   <ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Profiles\Xml\Dish Hopper-Joey.xml" />
     <EmbeddedResource Include="Profiles\Xml\Dish Hopper-Joey.xml" />
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Profiles\Xml\Popcorn Hour.xml" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
        Other similar extension points exist, see Microsoft.Common.targets.

+ 36 - 32
MediaBrowser.Dlna/PlayTo/PlayToController.cs

@@ -139,16 +139,21 @@ namespace MediaBrowser.Dlna.PlayTo
             try
             try
             {
             {
                 var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager);
                 var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager);
-                var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
+                if (streamInfo.Item != null)
+                {
+                    var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
 
 
-                var positionTicks = progress.PositionTicks;
+                    var positionTicks = progress.PositionTicks;
 
 
-                ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
+                    ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
+                }
 
 
                 streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager);
                 streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager);
-                progress = GetProgressInfo(e.NewMediaInfo, streamInfo);
+                if (streamInfo.Item == null) return;
+                
+                var newItemProgress = GetProgressInfo(e.NewMediaInfo, streamInfo);
 
 
-                await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
+                await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -161,6 +166,9 @@ namespace MediaBrowser.Dlna.PlayTo
             try
             try
             {
             {
                 var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
                 var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+
+                if (streamInfo.Item == null) return;
+
                 var progress = GetProgressInfo(e.MediaInfo, streamInfo);
                 var progress = GetProgressInfo(e.MediaInfo, streamInfo);
 
 
                 var positionTicks = progress.PositionTicks;
                 var positionTicks = progress.PositionTicks;
@@ -219,9 +227,14 @@ namespace MediaBrowser.Dlna.PlayTo
         {
         {
             try
             try
             {
             {
-                var info = GetProgressInfo(e.MediaInfo);
+                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+
+                if (info.Item != null)
+                {
+                    var progress = GetProgressInfo(e.MediaInfo, info);
 
 
-                await _sessionManager.OnPlaybackStart(info).ConfigureAwait(false);
+                    await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
+                }
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -233,9 +246,14 @@ namespace MediaBrowser.Dlna.PlayTo
         {
         {
             try
             try
             {
             {
-                var info = GetProgressInfo(e.MediaInfo);
+                var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
+
+                if (info.Item != null)
+                {
+                    var progress = GetProgressInfo(e.MediaInfo, info);
 
 
-                await _sessionManager.OnPlaybackProgress(info).ConfigureAwait(false);
+                    await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false);
+                }
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -243,13 +261,6 @@ namespace MediaBrowser.Dlna.PlayTo
             }
             }
         }
         }
 
 
-        private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo)
-        {
-            var info = StreamParams.ParseFromUrl(mediaInfo.Url, _libraryManager);
-
-            return GetProgressInfo(mediaInfo, info);
-        }
-
         private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo, StreamParams info)
         private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo, StreamParams info)
         {
         {
             var ticks = _device.Position.Ticks;
             var ticks = _device.Position.Ticks;
@@ -441,19 +452,9 @@ namespace MediaBrowser.Dlna.PlayTo
         private void AddItemFromId(Guid id, List<BaseItem> list)
         private void AddItemFromId(Guid id, List<BaseItem> list)
         {
         {
             var item = _libraryManager.GetItemById(id);
             var item = _libraryManager.GetItemById(id);
-            if (item.IsFolder)
-            {
-                foreach (var childId in _itemRepository.GetChildren(item.Id))
-                {
-                    AddItemFromId(childId, list);
-                }
-            }
-            else
+            if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video)
             {
             {
-                if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video)
-                {
-                    list.Add(item);
-                }
+                list.Add(item);
             }
             }
         }
         }
 
 
@@ -526,6 +527,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     streamInfo.TargetPacketLength,
                     streamInfo.TargetPacketLength,
                     streamInfo.TranscodeSeekInfo,
                     streamInfo.TranscodeSeekInfo,
                     streamInfo.IsTargetAnamorphic,
                     streamInfo.IsTargetAnamorphic,
+                    streamInfo.IsTargetCabac,
                     streamInfo.TargetRefFrames);
                     streamInfo.TargetRefFrames);
 
 
                 return list.FirstOrDefault();
                 return list.FirstOrDefault();
@@ -736,10 +738,10 @@ namespace MediaBrowser.Dlna.PlayTo
             if (media != null)
             if (media != null)
             {
             {
                 var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
                 var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
-                var progress = GetProgressInfo(media, info);
 
 
                 if (info.Item != null)
                 if (info.Item != null)
                 {
                 {
+                    var progress = GetProgressInfo(media, info);
                     var newPosition = progress.PositionTicks ?? 0;
                     var newPosition = progress.PositionTicks ?? 0;
 
 
                     var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
                     var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
@@ -762,10 +764,10 @@ namespace MediaBrowser.Dlna.PlayTo
             if (media != null)
             if (media != null)
             {
             {
                 var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
                 var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
-                var progress = GetProgressInfo(media, info);
 
 
                 if (info.Item != null)
                 if (info.Item != null)
                 {
                 {
+                    var progress = GetProgressInfo(media, info);
                     var newPosition = progress.PositionTicks ?? 0;
                     var newPosition = progress.PositionTicks ?? 0;
 
 
                     var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
                     var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
@@ -829,7 +831,9 @@ namespace MediaBrowser.Dlna.PlayTo
                     ItemId = GetItemId(url)
                     ItemId = GetItemId(url)
                 };
                 };
 
 
-                if (string.IsNullOrWhiteSpace(request.ItemId))
+                Guid parsedId;
+
+                if (string.IsNullOrWhiteSpace(request.ItemId) || !Guid.TryParse(request.ItemId, out parsedId))
                 {
                 {
                     return request;
                     return request;
                 }
                 }
@@ -882,7 +886,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
 
                 request.Item = string.IsNullOrWhiteSpace(request.ItemId)
                 request.Item = string.IsNullOrWhiteSpace(request.ItemId)
                     ? null
                     ? null
-                    : libraryManager.GetItemById(new Guid(request.ItemId));
+                    : libraryManager.GetItemById(parsedId);
 
 
                 var hasMediaSources = request.Item as IHasMediaSources;
                 var hasMediaSources = request.Item as IHasMediaSources;
 
 

+ 11 - 0
MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs

@@ -202,6 +202,17 @@ namespace MediaBrowser.Dlna.Profiles
                     Method = SubtitleDeliveryMethod.External
                     Method = SubtitleDeliveryMethod.External
                 }
                 }
             };
             };
+
+            ResponseProfiles = new[]
+            {
+                new ResponseProfile
+                {
+                    Type = DlnaProfileType.Video,
+                    Container = "ts",
+                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+                    MimeType = "video/vnd.dlna.mpeg-tts"
+                }
+            };
         }
         }
     }
     }
 }
 }

+ 178 - 0
MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs

@@ -0,0 +1,178 @@
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dlna.Profiles;
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+    [XmlRoot("Profile")]
+    public class PopcornHourProfile : DefaultProfile
+    {
+        public PopcornHourProfile()
+        {
+            Name = "Popcorn Hour";
+
+            TranscodingProfiles = new[]
+            {
+                new TranscodingProfile
+                {
+                    Container = "mp3",
+                    AudioCodec = "mp3",
+                    Type = DlnaProfileType.Audio
+                },
+
+                new TranscodingProfile
+                {
+                    Container = "mp4",
+                    Type = DlnaProfileType.Video,
+                    AudioCodec = "aac",
+                    VideoCodec = "h264",
+                    VideoProfile= "baseline"
+                },
+
+                new TranscodingProfile
+                {
+                    Container = "jpeg",
+                    Type = DlnaProfileType.Photo
+                }
+            };
+
+            DirectPlayProfiles = new[]
+            {
+                new DirectPlayProfile
+                {
+                    Container = "mp4,mov",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "h264,mpeg4",
+                    AudioCodec = "aac"
+                },
+
+                new DirectPlayProfile
+                {
+                    Container = "ts",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "h264",
+                    AudioCodec = "aac,ac3,eac3,mp3,mp2,pcm"
+                },
+
+                new DirectPlayProfile
+                {
+                    Container = "asf,wmv",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "wmv3,vc1",
+                    AudioCodec = "wmav2,wmapro"
+                },
+
+                new DirectPlayProfile
+                {
+                    Container = "avi",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "mpeg4,msmpeg4",
+                    AudioCodec = "mp3,ac3,eac3,mp2,pcm"
+                },
+
+                new DirectPlayProfile
+                {
+                    Container = "mkv",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "h264",
+                    AudioCodec = "aac,mp3,ac3,eac3,mp2,pcm"
+                },
+                new DirectPlayProfile
+                {
+                    Container = "aac,mp3,flac,ogg,wma,wav",
+                    Type = DlnaProfileType.Audio
+                },
+                new DirectPlayProfile
+                {
+                    Container = "jpeg,gif,bmp,png",
+                    Type = DlnaProfileType.Photo
+                }
+            };
+
+            CodecProfiles = new[]
+            {
+                new CodecProfile
+                {
+                    Type = CodecType.Video,
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.Width,
+                            Value = "1920"
+                        },
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.Height,
+                            Value = "1080"
+                        },
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.NotEquals,
+                            Property = ProfileConditionValue.IsAnamorphic,
+                            Value = "true",
+                            IsRequired = false
+                        }
+                    }
+                },
+
+                new CodecProfile
+                {
+                    Type = CodecType.VideoAudio,
+                    Codec = "aac",
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.AudioChannels,
+                            Value = "2",
+                            IsRequired = false
+                        }
+                    }
+                },
+
+                new CodecProfile
+                {
+                    Type = CodecType.Audio,
+                    Codec = "aac",
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.AudioChannels,
+                            Value = "2",
+                            IsRequired = false
+                        }
+                    }
+                },
+
+                new CodecProfile
+                {
+                    Type = CodecType.Audio,
+                    Codec = "mp3",
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.AudioChannels,
+                            Value = "2",
+                            IsRequired = false
+                        },
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.AudioBitrate,
+                            Value = "320000",
+                            IsRequired = false
+                        }
+                    }
+                }
+            };
+        }
+    }
+}

+ 1 - 8
MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs

@@ -1,7 +1,6 @@
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
 using MediaBrowser.Model.Dlna.Profiles;
 using MediaBrowser.Model.Dlna.Profiles;
-using MediaBrowser.Model.MediaInfo;
+using System.Xml.Serialization;
 
 
 namespace MediaBrowser.Dlna.Profiles
 namespace MediaBrowser.Dlna.Profiles
 {
 {
@@ -342,12 +341,6 @@ namespace MediaBrowser.Dlna.Profiles
 
 
             SubtitleProfiles = new[]
             SubtitleProfiles = new[]
             {
             {
-                new SubtitleProfile
-                {
-                    Format = "smi",
-                    Method = SubtitleDeliveryMethod.External,
-                    DidlMode = "CaptionInfoEx"
-                },
                 new SubtitleProfile
                 new SubtitleProfile
                 {
                 {
                     Format = "srt",
                     Format = "srt",

+ 1 - 1
MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs

@@ -1,6 +1,6 @@
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
 using MediaBrowser.Model.Dlna.Profiles;
 using MediaBrowser.Model.Dlna.Profiles;
+using System.Xml.Serialization;
 
 
 namespace MediaBrowser.Dlna.Profiles
 namespace MediaBrowser.Dlna.Profiles
 {
 {

+ 2 - 0
MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs

@@ -47,6 +47,8 @@ namespace MediaBrowser.Dlna.Profiles
             ProtocolInfo =
             ProtocolInfo =
                 "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
                 "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
 
 
+            DidlAlbumArtLimit = 1;
+            
             TranscodingProfiles = new[]
             TranscodingProfiles = new[]
             {
             {
                 new TranscodingProfile
                 new TranscodingProfile

+ 1 - 0
MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs

@@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
             Manufacturer = "Microsoft Corporation";
             Manufacturer = "Microsoft Corporation";
             ManufacturerUrl = "http://www.microsoft.com/";
             ManufacturerUrl = "http://www.microsoft.com/";
             SonyAggregationFlags = "10";
             SonyAggregationFlags = "10";
+            DidlAlbumArtLimit = 1;
 
 
             TranscodingProfiles = new[]
             TranscodingProfiles = new[]
             {
             {

+ 1 - 0
MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs

@@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
             Manufacturer = "Microsoft Corporation";
             Manufacturer = "Microsoft Corporation";
             ManufacturerUrl = "http://www.microsoft.com/";
             ManufacturerUrl = "http://www.microsoft.com/";
             SonyAggregationFlags = "10";
             SonyAggregationFlags = "10";
+            DidlAlbumArtLimit = 1;
 
 
             TranscodingProfiles = new[]
             TranscodingProfiles = new[]
             {
             {

+ 1 - 0
MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs

@@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
             Manufacturer = "Microsoft Corporation";
             Manufacturer = "Microsoft Corporation";
             ManufacturerUrl = "http://www.microsoft.com/";
             ManufacturerUrl = "http://www.microsoft.com/";
             SonyAggregationFlags = "10";
             SonyAggregationFlags = "10";
+            DidlAlbumArtLimit = 1;
 
 
             TranscodingProfiles = new[]
             TranscodingProfiles = new[]
             {
             {

+ 43 - 22
MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs

@@ -37,6 +37,49 @@ namespace MediaBrowser.Dlna.Profiles
 
 
             SonyAggregationFlags = "10";
             SonyAggregationFlags = "10";
             XDlnaDoc = "DMS-1.50";
             XDlnaDoc = "DMS-1.50";
+            DidlAlbumArtLimit = 1;
+
+            DirectPlayProfiles = new[]
+            {
+                new DirectPlayProfile
+                {
+                    Container = "avi",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "mpeg4",
+                    AudioCodec = "mp2,mp3"
+                },
+                new DirectPlayProfile
+                {
+                    Container = "ts",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "mpeg1video,mpeg2video,h264",
+                    AudioCodec = "ac3,mp2,mp3,aac"
+                },
+                new DirectPlayProfile
+                {
+                    Container = "mpeg",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "mpeg1video,mpeg2video",
+                    AudioCodec = "mp2"
+                },
+                new DirectPlayProfile
+                {
+                    Container = "mp4",
+                    Type = DlnaProfileType.Video,
+                    VideoCodec = "h264,mpeg4",
+                    AudioCodec = "aac,ac3"
+                },
+                new DirectPlayProfile
+                {
+                    Container = "aac,mp3,wav",
+                    Type = DlnaProfileType.Audio
+                },
+                new DirectPlayProfile
+                {
+                    Container = "jpeg,png,gif,bmp,tiff",
+                    Type = DlnaProfileType.Photo
+                }
+            };
 
 
             TranscodingProfiles = new[]
             TranscodingProfiles = new[]
             {
             {
@@ -185,28 +228,6 @@ namespace MediaBrowser.Dlna.Profiles
                             IsRequired = false
                             IsRequired = false
                         }
                         }
                     }
                     }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "he-aac"
-                        }
-                    }
                 }
                 }
             };
             };
 
 

+ 32 - 3
MediaBrowser.Dlna/Profiles/XboxOneProfile.cs

@@ -1,6 +1,6 @@
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
 using MediaBrowser.Model.Dlna.Profiles;
 using MediaBrowser.Model.Dlna.Profiles;
+using System.Xml.Serialization;
 
 
 namespace MediaBrowser.Dlna.Profiles
 namespace MediaBrowser.Dlna.Profiles
 {
 {
@@ -10,8 +10,9 @@ namespace MediaBrowser.Dlna.Profiles
         public XboxOneProfile()
         public XboxOneProfile()
         {
         {
             Name = "Xbox One";
             Name = "Xbox One";
-            XDlnaDoc = "DMS-1.50";
 
 
+            TimelineOffsetSeconds = 40;
+            
             Identification = new DeviceIdentification
             Identification = new DeviceIdentification
             {
             {
                 ModelName = "Xbox One",
                 ModelName = "Xbox One",
@@ -27,10 +28,16 @@ namespace MediaBrowser.Dlna.Profiles
                     Type = DlnaProfileType.Audio
                     Type = DlnaProfileType.Audio
                 },
                 },
                 new TranscodingProfile
                 new TranscodingProfile
+                {
+                    Container = "jpeg",
+                    VideoCodec = "jpeg",
+                    Type = DlnaProfileType.Photo
+                },
+                new TranscodingProfile
                 {
                 {
                     Container = "ts",
                     Container = "ts",
                     VideoCodec = "h264",
                     VideoCodec = "h264",
-                    AudioCodec = "ac3",
+                    AudioCodec = "aac",
                     Type = DlnaProfileType.Video,
                     Type = DlnaProfileType.Video,
                     EstimateContentLength = true
                     EstimateContentLength = true
                 }
                 }
@@ -114,6 +121,28 @@ namespace MediaBrowser.Dlna.Profiles
 
 
             CodecProfiles = new[]
             CodecProfiles = new[]
             {
             {
+                new CodecProfile
+                {
+                    Type = CodecType.Video,
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.NotEquals,
+                            Property = ProfileConditionValue.IsAnamorphic,
+                            Value = "true",
+                            IsRequired = false
+                        },
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.LessThanEqual,
+                            Property = ProfileConditionValue.VideoBitDepth,
+                            Value = "8",
+                            IsRequired = false
+                        }
+                    }
+                },
+
                 new CodecProfile
                 new CodecProfile
                 {
                 {
                     Type = CodecType.Video,
                     Type = CodecType.Video,

+ 22 - 9
MediaBrowser.Dlna/Profiles/Xml/Android.xml

@@ -10,6 +10,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -25,6 +26,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp4" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
     <DirectPlayProfile container="mp4" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
@@ -36,33 +39,43 @@
   </DirectPlayProfiles>
   </DirectPlayProfiles>
   <TranscodingProfiles>
   <TranscodingProfiles>
     <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
     <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
-    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
-    <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Static" />
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
+    <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Static" />
   </TranscodingProfiles>
   </TranscodingProfiles>
   <ContainerProfiles />
   <ContainerProfiles />
   <CodecProfiles>
   <CodecProfiles>
-    <CodecProfile type="Video">
+    <CodecProfile type="Video" codec="h264">
       <Conditions>
       <Conditions>
-        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
-        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="EqualsAny" property="VideoProfile" value="baseline|constrained baseline" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
         <ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
         <ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
+        <ProfileCondition condition="Equals" property="IsCabac" value="true" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="false" />
         <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
         <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
+        <ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
       </Conditions>
       </Conditions>
     </CodecProfile>
     </CodecProfile>
     <CodecProfile type="VideoAudio" codec="aac">
     <CodecProfile type="VideoAudio" codec="aac">
       <Conditions>
       <Conditions>
-        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
       </Conditions>
       </Conditions>
     </CodecProfile>
     </CodecProfile>
     <CodecProfile type="Audio" codec="aac">
     <CodecProfile type="Audio" codec="aac">
       <Conditions>
       <Conditions>
-        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
       </Conditions>
       </Conditions>
     </CodecProfile>
     </CodecProfile>
     <CodecProfile type="Audio" codec="mp3">
     <CodecProfile type="Audio" codec="mp3">
       <Conditions>
       <Conditions>
-        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
-        <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="320000" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="320000" isRequired="false" />
       </Conditions>
       </Conditions>
     </CodecProfile>
     </CodecProfile>
   </CodecProfiles>
   </CodecProfiles>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Default.xml

@@ -10,6 +10,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -25,6 +26,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp3,wma" type="Audio" />
     <DirectPlayProfile container="mp3,wma" type="Audio" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml

@@ -15,6 +15,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -30,6 +31,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
     <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainFolders>true</RequiresPlainFolders>
   <RequiresPlainFolders>true</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />
     <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -32,6 +33,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
     <DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
     <DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml

@@ -14,6 +14,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -29,6 +30,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
     <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio</SupportedMediaTypes>
   <SupportedMediaTypes>Audio</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
     <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -32,6 +33,8 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
     <XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
   </XmlRootAttributes>
   </XmlRootAttributes>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 24 - 0
MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml


+ 3 - 1
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
     <XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
   </XmlRootAttributes>
   </XmlRootAttributes>
@@ -109,7 +112,6 @@
     </ResponseProfile>
     </ResponseProfile>
   </ResponseProfiles>
   </ResponseProfiles>
   <SubtitleProfiles>
   <SubtitleProfiles>
-    <SubtitleProfile format="smi" method="External" didlMode="CaptionInfoEx" />
     <SubtitleProfile format="srt" method="External" didlMode="CaptionInfoEx" />
     <SubtitleProfile format="srt" method="External" didlMode="CaptionInfoEx" />
   </SubtitleProfiles>
   </SubtitleProfiles>
 </Profile>
 </Profile>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml

@@ -18,6 +18,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,6 +34,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit>1</DidlAlbumArtLimit>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,6 +34,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit>1</DidlAlbumArtLimit>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,6 +34,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit>1</DidlAlbumArtLimit>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,6 +34,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit>1</DidlAlbumArtLimit>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,6 +34,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
   </XmlRootAttributes>
   </XmlRootAttributes>

+ 9 - 8
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit>1</DidlAlbumArtLimit>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <AlbumArtPn>JPEG_TN</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -33,10 +34,16 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
-    <DirectPlayProfile container="mp3,wma" type="Audio" />
-    <DirectPlayProfile container="avi,mp4" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="aac,mp3,wav" type="Audio" />
+    <DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
   </DirectPlayProfiles>
   </DirectPlayProfiles>
   <TranscodingProfiles>
   <TranscodingProfiles>
     <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
     <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
@@ -77,12 +84,6 @@
         <ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="false" />
         <ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="false" />
       </Conditions>
       </Conditions>
     </CodecProfile>
     </CodecProfile>
-    <CodecProfile type="VideoAudio" codec="aac">
-      <Conditions>
-        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
-        <ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="true" />
-      </Conditions>
-    </CodecProfile>
   </CodecProfiles>
   </CodecProfiles>
   <ResponseProfiles>
   <ResponseProfiles>
     <ResponseProfile container="mp4,mov" audioCodec="aac" type="Video" mimeType="video/mp4">
     <ResponseProfile container="mp4,mov" audioCodec="aac" type="Video" mimeType="video/mp4">

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -32,6 +33,8 @@
   <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
     <DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml

@@ -14,6 +14,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -29,6 +30,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3,eac3,mp3,pcm" videoCodec="h264,mpeg4" type="Video" />
     <DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3,eac3,mp3,pcm" videoCodec="h264,mpeg4" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml

@@ -10,6 +10,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -25,6 +26,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp4,mov" audioCodec="aac,mp3" videoCodec="h264" type="Video" />
     <DirectPlayProfile container="mp4,mov" audioCodec="aac,mp3" videoCodec="h264" type="Video" />

+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml

@@ -17,6 +17,7 @@
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <ModelUrl>http://www.microsoft.com/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -32,6 +33,8 @@
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainFolders>true</RequiresPlainFolders>
   <RequiresPlainFolders>true</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
     <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml


+ 3 - 0
MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml

@@ -16,6 +16,7 @@
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <ModelUrl>http://mediabrowser.tv/</ModelUrl>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
   <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <DidlAlbumArtLimit xsi:nil="true" />
   <SupportedMediaTypes>Audio</SupportedMediaTypes>
   <SupportedMediaTypes>Audio</SupportedMediaTypes>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <AlbumArtPn>JPEG_SM</AlbumArtPn>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
   <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -31,6 +32,8 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
+  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
+  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>
     <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
     <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />

+ 1 - 0
MediaBrowser.Dlna/Ssdp/SsdpHandler.cs

@@ -172,6 +172,7 @@ namespace MediaBrowser.Dlna.Ssdp
                     values["ST"] = d.Type;
                     values["ST"] = d.Type;
                     values["USN"] = d.USN;
                     values["USN"] = d.USN;
 
 
+                    SendDatagram(header, values, endpoint, null, true);
                     SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true);
                     SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true);
                     //SendDatagram(header, values, endpoint, null, true);
                     //SendDatagram(header, values, endpoint, null, true);
 
 

+ 14 - 4
MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs

@@ -1,7 +1,8 @@
-using System.Xml;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
+using System;
+using System.Xml;
 
 
 namespace MediaBrowser.LocalMetadata.Parsers
 namespace MediaBrowser.LocalMetadata.Parsers
 {
 {
@@ -26,8 +27,17 @@ namespace MediaBrowser.LocalMetadata.Parsers
             switch (reader.Name)
             switch (reader.Name)
             {
             {
                 case "Artist":
                 case "Artist":
-                    item.Artist = reader.ReadElementContentAsString();
-                    break;
+                    {
+                        var val = reader.ReadElementContentAsString();
+
+                        if (!string.IsNullOrWhiteSpace(val))
+                        {
+                            var artists = val.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+                            item.Artists.AddRange(artists);
+                        }
+
+                        break;
+                    }
 
 
                 case "Album":
                 case "Album":
                     item.Album = reader.ReadElementContentAsString();
                     item.Album = reader.ReadElementContentAsString();

+ 2 - 2
MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs

@@ -78,9 +78,9 @@ namespace MediaBrowser.LocalMetadata.Savers
 
 
             if (musicVideo != null)
             if (musicVideo != null)
             {
             {
-                if (!string.IsNullOrEmpty(musicVideo.Artist))
+                if (musicVideo.Artists.Count > 0)
                 {
                 {
-                    builder.Append("<Artist>" + SecurityElement.Escape(musicVideo.Artist) + "</Artist>");
+                    builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>");
                 }
                 }
                 if (!string.IsNullOrEmpty(musicVideo.Album))
                 if (!string.IsNullOrEmpty(musicVideo.Album))
                 {
                 {

+ 7 - 0
MediaBrowser.MediaInfo/MediaInfoLib.cs

@@ -24,6 +24,12 @@ namespace MediaBrowser.MediaInfo
                 result.IsInterlaced = text.IndexOf("interlac", StringComparison.OrdinalIgnoreCase) != -1;
                 result.IsInterlaced = text.IndexOf("interlac", StringComparison.OrdinalIgnoreCase) != -1;
             }
             }
 
 
+            text = GetValue(lib, videoStreamIndex, new[] { "Format_Settings_CABAC", "Format_Settings_CABAC/String" });
+            if (!string.IsNullOrWhiteSpace(text))
+            {
+                result.IsCabac = string.Equals(text, "yes", StringComparison.OrdinalIgnoreCase);
+            }
+
             int bitDepth;
             int bitDepth;
             text = GetValue(lib, videoStreamIndex, new[] { "BitDepth", "BitDepth/String" });
             text = GetValue(lib, videoStreamIndex, new[] { "BitDepth", "BitDepth/String" });
 
 
@@ -51,6 +57,7 @@ namespace MediaBrowser.MediaInfo
 
 
     public class MediaInfoResult
     public class MediaInfoResult
     {
     {
+        public bool? IsCabac { get; set; }
         public bool? IsInterlaced { get; set; }
         public bool? IsInterlaced { get; set; }
         public int? BitDepth { get; set; }
         public int? BitDepth { get; set; }
         public int? RefFrames { get; set; }
         public int? RefFrames { get; set; }

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

@@ -413,6 +413,9 @@
     <Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
     <Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
       <Link>Dto\GameSystemSummary.cs</Link>
       <Link>Dto\GameSystemSummary.cs</Link>
     </Compile>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
+      <Link>Dto\IHasServerId.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
     <Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
       <Link>Dto\IItemDto.cs</Link>
       <Link>Dto\IItemDto.cs</Link>
     </Compile>
     </Compile>
@@ -1088,9 +1091,6 @@
     <Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
     <Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
       <Link>Users\AuthenticationResult.cs</Link>
       <Link>Users\AuthenticationResult.cs</Link>
     </Compile>
     </Compile>
-    <Compile Include="..\MediaBrowser.Model\Weather\WeatherUnits.cs">
-      <Link>Weather\WeatherUnits.cs</Link>
-    </Compile>
     <Compile Include="..\SharedVersion.cs">
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     </Compile>

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

@@ -378,6 +378,9 @@
     <Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
     <Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
       <Link>Dto\GameSystemSummary.cs</Link>
       <Link>Dto\GameSystemSummary.cs</Link>
     </Compile>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
+      <Link>Dto\IHasServerId.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
     <Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
       <Link>Dto\IItemDto.cs</Link>
       <Link>Dto\IItemDto.cs</Link>
     </Compile>
     </Compile>
@@ -1047,9 +1050,6 @@
     <Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
     <Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
       <Link>Users\AuthenticationResult.cs</Link>
       <Link>Users\AuthenticationResult.cs</Link>
     </Compile>
     </Compile>
-    <Compile Include="..\MediaBrowser.Model\Weather\WeatherUnits.cs">
-      <Link>Weather\WeatherUnits.cs</Link>
-    </Compile>
     <Compile Include="..\SharedVersion.cs">
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     </Compile>

+ 5 - 3
MediaBrowser.Model/ApiClient/IConnectionManager.cs

@@ -30,7 +30,9 @@ namespace MediaBrowser.Model.ApiClient
         /// Occurs when [connect user sign out].
         /// Occurs when [connect user sign out].
         /// </summary>
         /// </summary>
         event EventHandler<EventArgs> ConnectUserSignOut;
         event EventHandler<EventArgs> ConnectUserSignOut;
-
+        [Obsolete]
+        event EventHandler<EventArgs> RemoteLoggedOut;
+        
         /// <summary>
         /// <summary>
         /// Gets the connect user.
         /// Gets the connect user.
         /// </summary>
         /// </summary>
@@ -41,8 +43,8 @@ namespace MediaBrowser.Model.ApiClient
         /// Gets the API client.
         /// Gets the API client.
         /// </summary>
         /// </summary>
         /// <param name="item">The item.</param>
         /// <param name="item">The item.</param>
-        /// <returns>MediaBrowser.Model.ApiClient.IApiClient.</returns>
-        IApiClient GetApiClient(BaseItemDto item);
+        /// <returns>IApiClient.</returns>
+        IApiClient GetApiClient(IHasServerId item);
 
 
         /// <summary>
         /// <summary>
         /// Connects the specified cancellation token.
         /// Connects the specified cancellation token.

+ 5 - 0
MediaBrowser.Model/Configuration/MetadataConfiguration.cs

@@ -4,5 +4,10 @@ namespace MediaBrowser.Model.Configuration
     public class MetadataConfiguration
     public class MetadataConfiguration
     {
     {
         public bool UseFileCreationTimeForDateAdded { get; set; }
         public bool UseFileCreationTimeForDateAdded { get; set; }
+
+        public MetadataConfiguration()
+        {
+            UseFileCreationTimeForDateAdded = true;
+        }
     }
     }
 }
 }

+ 2 - 0
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -180,6 +180,8 @@ namespace MediaBrowser.Model.Configuration
 
 
         public bool SaveMetadataHidden { get; set; }
         public bool SaveMetadataHidden { get; set; }
 
 
+        public bool PlaylistImagesDeleted { get; set; }
+
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
         /// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
         /// </summary>
         /// </summary>

+ 3 - 0
MediaBrowser.Model/Configuration/UserConfiguration.cs

@@ -88,6 +88,8 @@ namespace MediaBrowser.Model.Configuration
 
 
         public AccessSchedule[] AccessSchedules { get; set; }
         public AccessSchedule[] AccessSchedules { get; set; }
 
 
+        public bool EnableUserPreferenceAccess { get; set; }
+        
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="UserConfiguration" /> class.
         /// Initializes a new instance of the <see cref="UserConfiguration" /> class.
         /// </summary>
         /// </summary>
@@ -112,6 +114,7 @@ namespace MediaBrowser.Model.Configuration
             SyncConnectImage = true;
             SyncConnectImage = true;
             IncludeTrailersInSuggestions = true;
             IncludeTrailersInSuggestions = true;
             EnableCinemaMode = true;
             EnableCinemaMode = true;
+            EnableUserPreferenceAccess = true;
 
 
             AccessSchedules = new AccessSchedule[] { };
             AccessSchedules = new AccessSchedule[] { };
         }
         }

+ 1 - 1
MediaBrowser.Model/Devices/LocalFileInfo.cs

@@ -4,7 +4,7 @@ namespace MediaBrowser.Model.Devices
     public class LocalFileInfo
     public class LocalFileInfo
     {
     {
         public string Name { get; set; }
         public string Name { get; set; }
-        public string FullPath { get; set; }
+        public string Id { get; set; }
         public string Album { get; set; }
         public string Album { get; set; }
         public string MimeType { get; set; }
         public string MimeType { get; set; }
     }
     }

+ 3 - 0
MediaBrowser.Model/Dlna/ConditionProcessor.cs

@@ -19,6 +19,7 @@ namespace MediaBrowser.Model.Dlna
             int? packetLength,
             int? packetLength,
             TransportStreamTimestamp? timestamp,
             TransportStreamTimestamp? timestamp,
             bool? isAnamorphic,
             bool? isAnamorphic,
+            bool? isCabac,
             int? refFrames)
             int? refFrames)
         {
         {
             switch (condition.Property)
             switch (condition.Property)
@@ -31,6 +32,8 @@ namespace MediaBrowser.Model.Dlna
                     return true;
                     return true;
                 case ProfileConditionValue.IsAnamorphic:
                 case ProfileConditionValue.IsAnamorphic:
                     return IsConditionSatisfied(condition, isAnamorphic);
                     return IsConditionSatisfied(condition, isAnamorphic);
+                case ProfileConditionValue.IsCabac:
+                    return IsConditionSatisfied(condition, isCabac);
                 case ProfileConditionValue.VideoFramerate:
                 case ProfileConditionValue.VideoFramerate:
                     return IsConditionSatisfied(condition, videoFramerate);
                     return IsConditionSatisfied(condition, videoFramerate);
                 case ProfileConditionValue.VideoLevel:
                 case ProfileConditionValue.VideoLevel:

+ 2 - 0
MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs

@@ -116,6 +116,7 @@ namespace MediaBrowser.Model.Dlna
             int? packetLength,
             int? packetLength,
             TranscodeSeekInfo transcodeSeekInfo,
             TranscodeSeekInfo transcodeSeekInfo,
             bool? isAnamorphic,
             bool? isAnamorphic,
+            bool? isCabac,
             int? refFrames)
             int? refFrames)
         {
         {
             // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
             // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
@@ -156,6 +157,7 @@ namespace MediaBrowser.Model.Dlna
                 packetLength,
                 packetLength,
                 timestamp,
                 timestamp,
                 isAnamorphic,
                 isAnamorphic,
+                isCabac,
                 refFrames);
                 refFrames);
 
 
             List<string> orgPnValues = new List<string>();
             List<string> orgPnValues = new List<string>();

+ 4 - 1
MediaBrowser.Model/Dlna/DeviceProfile.cs

@@ -35,7 +35,9 @@ namespace MediaBrowser.Model.Dlna
         public string ModelUrl { get; set; }
         public string ModelUrl { get; set; }
         public string SerialNumber { get; set; }
         public string SerialNumber { get; set; }
         public bool IgnoreTranscodeByteRangeRequests { get; set; }
         public bool IgnoreTranscodeByteRangeRequests { get; set; }
+
         public bool EnableAlbumArtInDidl { get; set; }
         public bool EnableAlbumArtInDidl { get; set; }
+        public int? DidlAlbumArtLimit { get; set; }
 
 
         public string SupportedMediaTypes { get; set; }
         public string SupportedMediaTypes { get; set; }
 
 
@@ -279,6 +281,7 @@ namespace MediaBrowser.Model.Dlna
             int? packetLength,
             int? packetLength,
             TransportStreamTimestamp timestamp,
             TransportStreamTimestamp timestamp,
             bool? isAnamorphic,
             bool? isAnamorphic,
+            bool? isCabac,
             int? refFrames)
             int? refFrames)
         {
         {
             container = StringHelper.TrimStart((container ?? string.Empty), '.');
             container = StringHelper.TrimStart((container ?? string.Empty), '.');
@@ -313,7 +316,7 @@ namespace MediaBrowser.Model.Dlna
                 var anyOff = false;
                 var anyOff = false;
                 foreach (ProfileCondition c in i.Conditions)
                 foreach (ProfileCondition c in i.Conditions)
                 {
                 {
-                    if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
+                    if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
                     {
                     {
                         anyOff = true;
                         anyOff = true;
                         break;
                         break;

+ 2 - 1
MediaBrowser.Model/Dlna/ProfileConditionValue.cs

@@ -16,6 +16,7 @@
         VideoProfile = 11,
         VideoProfile = 11,
         VideoTimestamp = 12,
         VideoTimestamp = 12,
         IsAnamorphic = 13,
         IsAnamorphic = 13,
-        RefFrames = 14
+        RefFrames = 14,
+        IsCabac = 15
     }
     }
 }
 }

+ 10 - 3
MediaBrowser.Model/Dlna/Profiles/AndroidProfile.cs

@@ -6,8 +6,14 @@ namespace MediaBrowser.Model.Dlna.Profiles
     [XmlRoot("Profile")]
     [XmlRoot("Profile")]
     public class AndroidProfile : DefaultProfile
     public class AndroidProfile : DefaultProfile
     {
     {
-        public AndroidProfile(bool supportsHls, 
-            bool supportsMpegDash, 
+        public AndroidProfile()
+            : this(true, true, new[] { "baseline", "constrained baseline" })
+        {
+
+        }
+
+        public AndroidProfile(bool supportsHls,
+            bool supportsMpegDash,
             string[] supportedH264Profiles)
             string[] supportedH264Profiles)
         {
         {
             Name = "Android";
             Name = "Android";
@@ -108,7 +114,8 @@ namespace MediaBrowser.Model.Dlna.Profiles
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Width, "1920"),
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Width, "1920"),
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Height, "1080"),
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Height, "1080"),
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.VideoBitDepth, "8"),
                         new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.VideoBitDepth, "8"),
-                        new ProfileCondition(ProfileConditionType.NotEquals, ProfileConditionValue.IsAnamorphic, "true")
+                        new ProfileCondition(ProfileConditionType.NotEquals, ProfileConditionValue.IsAnamorphic, "true"),
+                        new ProfileCondition(ProfileConditionType.Equals, ProfileConditionValue.IsCabac, "true")
                     }
                     }
                 },
                 },
 
 

+ 4 - 2
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -419,6 +419,7 @@ namespace MediaBrowser.Model.Dlna
             string videoProfile = videoStream == null ? null : videoStream.Profile;
             string videoProfile = videoStream == null ? null : videoStream.Profile;
             float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
             float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
             bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic;
             bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic;
+            bool? isCabac = videoStream == null ? null : videoStream.IsCabac;
 
 
             int? audioBitrate = audioStream == null ? null : audioStream.BitRate;
             int? audioBitrate = audioStream == null ? null : audioStream.BitRate;
             int? audioChannels = audioStream == null ? null : audioStream.Channels;
             int? audioChannels = audioStream == null ? null : audioStream.Channels;
@@ -431,7 +432,7 @@ namespace MediaBrowser.Model.Dlna
             // Check container conditions
             // Check container conditions
             foreach (ProfileCondition i in conditions)
             foreach (ProfileCondition i in conditions)
             {
             {
-                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
+                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
                 {
                 {
                     return null;
                     return null;
                 }
                 }
@@ -458,7 +459,7 @@ namespace MediaBrowser.Model.Dlna
 
 
             foreach (ProfileCondition i in conditions)
             foreach (ProfileCondition i in conditions)
             {
             {
-                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
+                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
                 {
                 {
                     return null;
                     return null;
                 }
                 }
@@ -647,6 +648,7 @@ namespace MediaBrowser.Model.Dlna
                         }
                         }
                     case ProfileConditionValue.AudioProfile:
                     case ProfileConditionValue.AudioProfile:
                     case ProfileConditionValue.IsAnamorphic:
                     case ProfileConditionValue.IsAnamorphic:
+                    case ProfileConditionValue.IsCabac:
                     case ProfileConditionValue.Has64BitOffsets:
                     case ProfileConditionValue.Has64BitOffsets:
                     case ProfileConditionValue.PacketLength:
                     case ProfileConditionValue.PacketLength:
                     case ProfileConditionValue.VideoTimestamp:
                     case ProfileConditionValue.VideoTimestamp:

+ 13 - 0
MediaBrowser.Model/Dlna/StreamInfo.cs

@@ -456,6 +456,19 @@ namespace MediaBrowser.Model.Dlna
             }
             }
         }
         }
 
 
+        public bool? IsTargetCabac
+        {
+            get
+            {
+                if (IsDirectStream)
+                {
+                    return TargetVideoStream == null ? null : TargetVideoStream.IsCabac;
+                }
+
+                return true;
+            }
+        }
+
         public int? TargetWidth
         public int? TargetWidth
         {
         {
             get
             get

+ 9 - 2
MediaBrowser.Model/Dto/BaseItemDto.cs

@@ -16,7 +16,7 @@ namespace MediaBrowser.Model.Dto
     /// This holds information about a BaseItem in a format that is convenient for the client.
     /// This holds information about a BaseItem in a format that is convenient for the client.
     /// </summary>
     /// </summary>
     [DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")]
     [DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")]
-    public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto
+    public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto, IHasServerId
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the name.
         /// Gets or sets the name.
@@ -24,6 +24,12 @@ namespace MediaBrowser.Model.Dto
         /// <value>The name.</value>
         /// <value>The name.</value>
         public string Name { get; set; }
         public string Name { get; set; }
 
 
+        /// <summary>
+        /// Gets or sets the server identifier.
+        /// </summary>
+        /// <value>The server identifier.</value>
+        public string ServerId { get; set; }
+        
         /// <summary>
         /// <summary>
         /// Gets or sets the id.
         /// Gets or sets the id.
         /// </summary>
         /// </summary>
@@ -43,7 +49,8 @@ namespace MediaBrowser.Model.Dto
         public DateTime? DateCreated { get; set; }
         public DateTime? DateCreated { get; set; }
 
 
         public DateTime? DateLastMediaAdded { get; set; }
         public DateTime? DateLastMediaAdded { get; set; }
-        
+        public ExtraType? ExtraType { get; set; }
+      
         public int? AirsBeforeSeasonNumber { get; set; }
         public int? AirsBeforeSeasonNumber { get; set; }
         public int? AirsAfterSeasonNumber { get; set; }
         public int? AirsAfterSeasonNumber { get; set; }
         public int? AirsBeforeEpisodeNumber { get; set; }
         public int? AirsBeforeEpisodeNumber { get; set; }

+ 8 - 0
MediaBrowser.Model/Dto/IHasServerId.cs

@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Dto
+{
+    public interface IHasServerId
+    {
+        string ServerId { get; }
+    }
+}

+ 7 - 1
MediaBrowser.Model/Dto/UserDto.cs

@@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Dto
     /// Class UserDto
     /// Class UserDto
     /// </summary>
     /// </summary>
     [DebuggerDisplay("Name = {Name}, ID = {Id}, HasPassword = {HasPassword}")]
     [DebuggerDisplay("Name = {Name}, ID = {Id}, HasPassword = {HasPassword}")]
-    public class UserDto : IHasPropertyChangedEvent, IItemDto
+    public class UserDto : IHasPropertyChangedEvent, IItemDto, IHasServerId
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the name.
         /// Gets or sets the name.
@@ -20,6 +20,12 @@ namespace MediaBrowser.Model.Dto
         /// <value>The name.</value>
         /// <value>The name.</value>
         public string Name { get; set; }
         public string Name { get; set; }
 
 
+        /// <summary>
+        /// Gets or sets the server identifier.
+        /// </summary>
+        /// <value>The server identifier.</value>
+        public string ServerId { get; set; }
+        
         /// <summary>
         /// <summary>
         /// Gets or sets the name of the connect user.
         /// Gets or sets the name of the connect user.
         /// </summary>
         /// </summary>

+ 6 - 0
MediaBrowser.Model/Entities/MediaStream.cs

@@ -175,5 +175,11 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// </summary>
         /// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value>
         /// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value>
         public bool? IsAnamorphic { get; set; }
         public bool? IsAnamorphic { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance is cabac.
+        /// </summary>
+        /// <value><c>null</c> if [is cabac] contains no value, <c>true</c> if [is cabac]; otherwise, <c>false</c>.</value>
+        public bool? IsCabac { get; set; }
     }
     }
 }
 }

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

@@ -121,6 +121,7 @@
     <Compile Include="Dlna\SubtitleDeliveryMethod.cs" />
     <Compile Include="Dlna\SubtitleDeliveryMethod.cs" />
     <Compile Include="Dlna\SubtitleStreamInfo.cs" />
     <Compile Include="Dlna\SubtitleStreamInfo.cs" />
     <Compile Include="Drawing\ImageOrientation.cs" />
     <Compile Include="Drawing\ImageOrientation.cs" />
+    <Compile Include="Dto\IHasServerId.cs" />
     <Compile Include="Dto\MediaSourceType.cs" />
     <Compile Include="Dto\MediaSourceType.cs" />
     <Compile Include="Dto\StreamOptions.cs" />
     <Compile Include="Dto\StreamOptions.cs" />
     <Compile Include="Dto\VideoStreamOptions.cs" />
     <Compile Include="Dto\VideoStreamOptions.cs" />
@@ -402,7 +403,6 @@
     <Compile Include="Updates\PackageInfo.cs" />
     <Compile Include="Updates\PackageInfo.cs" />
     <Compile Include="Updates\PackageVersionInfo.cs" />
     <Compile Include="Updates\PackageVersionInfo.cs" />
     <Compile Include="Users\AuthenticationResult.cs" />
     <Compile Include="Users\AuthenticationResult.cs" />
-    <Compile Include="Weather\WeatherUnits.cs" />
     <None Include="Fody.targets" />
     <None Include="Fody.targets" />
     <None Include="FodyWeavers.xml" />
     <None Include="FodyWeavers.xml" />
     <None Include="MediaBrowser.Model.snk" />
     <None Include="MediaBrowser.Model.snk" />

+ 1 - 20
MediaBrowser.Model/Querying/ItemsResult.cs

@@ -5,26 +5,7 @@ namespace MediaBrowser.Model.Querying
     /// <summary>
     /// <summary>
     /// Represents the result of a query for items
     /// Represents the result of a query for items
     /// </summary>
     /// </summary>
-    public class ItemsResult
+    public class ItemsResult : QueryResult<BaseItemDto>
     {
     {
-        /// <summary>
-        /// The set of items returned based on sorting, paging, etc
-        /// </summary>
-        /// <value>The items.</value>
-        public BaseItemDto[] Items { get; set; }
-
-        /// <summary>
-        /// The total number of records available
-        /// </summary>
-        /// <value>The total record count.</value>
-        public int TotalRecordCount { get; set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemsResult"/> class.
-        /// </summary>
-        public ItemsResult()
-        {
-            Items = new BaseItemDto[] { };
-        }
     }
     }
 }
 }

+ 0 - 17
MediaBrowser.Model/Weather/WeatherUnits.cs

@@ -1,17 +0,0 @@
-namespace MediaBrowser.Model.Weather
-{
-    /// <summary>
-    /// Enum WeatherUnits
-    /// </summary>
-    public enum WeatherUnits
-    {
-        /// <summary>
-        /// The fahrenheit
-        /// </summary>
-        Fahrenheit,
-        /// <summary>
-        /// The celsius
-        /// </summary>
-        Celsius
-    }
-}

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

@@ -286,6 +286,7 @@ namespace MediaBrowser.Providers.MediaInfo
                     {
                     {
                         var result = new MediaInfoLib().GetVideoInfo(video.Path);
                         var result = new MediaInfoLib().GetVideoInfo(video.Path);
 
 
+                        videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac;
                         videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced;
                         videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced;
                         videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth;
                         videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth;
                         videoStream.RefFrames = result.RefFrames;
                         videoStream.RefFrames = result.RefFrames;

+ 22 - 6
MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs

@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Movies
 {
 {
     class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask
     class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask
     {
     {
-        private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/";
+        private const string UpdatesUrl = "http://webservice.fanart.tv/v3/movies/latest?api_key={0}&date={1}";
 
 
         /// <summary>
         /// <summary>
         /// The _HTTP client
         /// The _HTTP client
@@ -118,11 +118,26 @@ namespace MediaBrowser.Providers.Movies
                         return new List<string>();
                         return new List<string>();
                     }
                     }
 
 
-                    var updates = _jsonSerializer.DeserializeFromString<List<FanartUpdatesPostScanTask.FanArtUpdate>>(json);
+                    var updates = _jsonSerializer.DeserializeFromString<List<RootObject>>(json);
 
 
                     var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
                     var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
 
 
-                    return updates.Select(i => i.id).Where(existingDictionary.ContainsKey);
+                    return updates.SelectMany(i =>
+                    {
+                        var list = new List<string>();
+
+                        if (!string.IsNullOrWhiteSpace(i.imdb_id))
+                        {
+                            list.Add(i.imdb_id);
+                        }
+                        if (!string.IsNullOrWhiteSpace(i.tmdb_id))
+                        {
+                            list.Add(i.tmdb_id);
+                        }
+
+                        return list;
+
+                    }).Where(existingDictionary.ContainsKey);
                 }
                 }
             }
             }
         }
         }
@@ -136,7 +151,7 @@ namespace MediaBrowser.Providers.Movies
             {
             {
                 _logger.Info("Updating movie " + id);
                 _logger.Info("Updating movie " + id);
 
 
-                await FanartMovieImageProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false);
+                await FanartMovieImageProvider.Current.DownloadMovieJson(id, cancellationToken).ConfigureAwait(false);
 
 
                 numComplete++;
                 numComplete++;
                 double percent = numComplete;
                 double percent = numComplete;
@@ -157,9 +172,10 @@ namespace MediaBrowser.Providers.Movies
             return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
             return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
         }
         }
 
 
-        public class FanArtUpdate
+        public class RootObject
         {
         {
-            public string id { get; set; }
+            public string tmdb_id { get; set; }
+            public string imdb_id { get; set; }
             public string name { get; set; }
             public string name { get; set; }
             public string new_images { get; set; }
             public string new_images { get; set; }
             public string total_images { get; set; }
             public string total_images { get; set; }

+ 99 - 206
MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs

@@ -1,25 +1,22 @@
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Providers;
 using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Serialization;
 using MediaBrowser.Providers.Music;
 using MediaBrowser.Providers.Music;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
-using System.Text;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using System.Xml;
 
 
 namespace MediaBrowser.Providers.Movies
 namespace MediaBrowser.Providers.Movies
 {
 {
@@ -29,16 +26,19 @@ namespace MediaBrowser.Providers.Movies
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly IHttpClient _httpClient;
         private readonly IHttpClient _httpClient;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
+        private readonly IJsonSerializer _json;
 
 
-        private const string FanArtBaseUrl = "http://api.fanart.tv/webservice/movie/{0}/{1}/xml/all/1/1";
+        private const string FanArtBaseUrl = "http://webservice.fanart.tv/v3/movies/{1}?api_key={0}";
+        // &client_key=52c813aa7b8c8b3bb87f4797532a2f8c
 
 
         internal static FanartMovieImageProvider Current;
         internal static FanartMovieImageProvider Current;
 
 
-        public FanartMovieImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
+        public FanartMovieImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json)
         {
         {
             _config = config;
             _config = config;
             _httpClient = httpClient;
             _httpClient = httpClient;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
+            _json = json;
 
 
             Current = this;
             Current = this;
         }
         }
@@ -88,13 +88,13 @@ namespace MediaBrowser.Providers.Movies
 
 
             if (!string.IsNullOrEmpty(movieId))
             if (!string.IsNullOrEmpty(movieId))
             {
             {
-                await EnsureMovieXml(movieId, cancellationToken).ConfigureAwait(false);
+                await EnsureMovieJson(movieId, cancellationToken).ConfigureAwait(false);
 
 
-                var xmlPath = GetFanartXmlPath(movieId);
+                var path = GetFanartJsonPath(movieId);
 
 
                 try
                 try
                 {
                 {
-                    AddImages(list, xmlPath, cancellationToken);
+                    AddImages(list, path, cancellationToken);
                 }
                 }
                 catch (FileNotFoundException)
                 catch (FileNotFoundException)
                 {
                 {
@@ -130,198 +130,63 @@ namespace MediaBrowser.Providers.Movies
                 .ThenByDescending(i => i.CommunityRating ?? 0);
                 .ThenByDescending(i => i.CommunityRating ?? 0);
         }
         }
 
 
-        private void AddImages(List<RemoteImageInfo> list, string xmlPath, CancellationToken cancellationToken)
+        private void AddImages(List<RemoteImageInfo> list, string path, CancellationToken cancellationToken)
         {
         {
-            using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
-            {
-                // Use XmlReader for best performance
-                using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
-                {
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true,
-                    ValidationType = ValidationType.None
-                }))
-                {
-                    reader.MoveToContent();
-
-                    // Loop through each element
-                    while (reader.Read())
-                    {
-                        cancellationToken.ThrowIfCancellationRequested();
+            var root = _json.DeserializeFromFile<RootObject>(path);
 
 
-                        if (reader.NodeType == XmlNodeType.Element)
-                        {
-                            switch (reader.Name)
-                            {
-                                case "movie":
-                                    {
-                                        using (var subReader = reader.ReadSubtree())
-                                        {
-                                            AddImages(list, subReader, cancellationToken);
-                                        }
-                                        break;
-                                    }
-
-                                default:
-                                    reader.Skip();
-                                    break;
-                            }
-                        }
-                    }
-                }
-            }
+            AddImages(list, root, cancellationToken);
         }
         }
 
 
-        private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken)
+        private void AddImages(List<RemoteImageInfo> list, RootObject obj, CancellationToken cancellationToken)
         {
         {
-            reader.MoveToContent();
-
-            while (reader.Read())
-            {
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        case "hdmoviecleararts":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 1000, 562);
-                                }
-                                break;
-                            }
-                        case "hdmovielogos":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 800, 310);
-                                }
-                                break;
-                            }
-                        case "moviediscs":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Disc, 1000, 1000);
-                                }
-                                break;
-                            }
-                        case "movieposters":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Primary, 1000, 1426);
-                                }
-                                break;
-                            }
-                        case "movielogos":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 400, 155);
-                                }
-                                break;
-                            }
-                        case "moviearts":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 500, 281);
-                                }
-                                break;
-                            }
-                        case "moviethumbs":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 1000, 562);
-                                }
-                                break;
-                            }
-                        case "moviebanners":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Banner, 1000, 185);
-                                }
-                                break;
-                            }
-                        case "moviebackgrounds":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080);
-                                }
-                                break;
-                            }
-                        default:
-                            {
-                                using (reader.ReadSubtree())
-                                {
-                                }
-                                break;
-                            }
-                    }
-                }
-            }
+            PopulateImages(list, obj.hdmovieclearart, ImageType.Art, 1000, 562);
+            PopulateImages(list, obj.hdmovielogo, ImageType.Logo, 800, 310);
+            PopulateImages(list, obj.moviedisc, ImageType.Disc, 1000, 1000);
+            PopulateImages(list, obj.movieposter, ImageType.Primary, 1000, 1426);
+            PopulateImages(list, obj.movielogo, ImageType.Logo, 400, 155);
+            PopulateImages(list, obj.movieart, ImageType.Art, 500, 281);
+            PopulateImages(list, obj.moviethumb, ImageType.Thumb, 1000, 562);
+            PopulateImages(list, obj.moviebanner, ImageType.Banner, 1000, 185);
+            PopulateImages(list, obj.moviebackground, ImageType.Backdrop, 1920, 1080);
         }
         }
 
 
-        private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height)
+        private void PopulateImages(List<RemoteImageInfo> list, List<Image> images, ImageType type, int width, int height)
         {
         {
-            reader.MoveToContent();
+            if (images == null)
+            {
+                return;
+            }
 
 
-            while (reader.Read())
+            list.AddRange(images.Select(i =>
             {
             {
-                cancellationToken.ThrowIfCancellationRequested();
+                var url = i.url;
 
 
-                if (reader.NodeType == XmlNodeType.Element)
+                if (!string.IsNullOrEmpty(url))
                 {
                 {
-                    switch (reader.Name)
+                    var likesString = i.likes;
+                    int likes;
+
+                    var info = new RemoteImageInfo
+                    {
+                        RatingType = RatingType.Likes,
+                        Type = type,
+                        Width = width,
+                        Height = height,
+                        ProviderName = Name,
+                        Url = url,
+                        Language = i.lang
+                    };
+
+                    if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
                     {
                     {
-                        case "hdmovielogo":
-                        case "moviedisc":
-                        case "hdmovieclearart":
-                        case "movieposter":
-                        case "movielogo":
-                        case "movieart":
-                        case "moviethumb":
-                        case "moviebanner":
-                        case "moviebackground":
-                            {
-                                var url = reader.GetAttribute("url");
-
-                                if (!string.IsNullOrEmpty(url))
-                                {
-                                    var likesString = reader.GetAttribute("likes");
-                                    int likes;
-
-                                    var info = new RemoteImageInfo
-                                    {
-                                        RatingType = RatingType.Likes,
-                                        Type = type,
-                                        Width = width,
-                                        Height = height,
-                                        ProviderName = Name,
-                                        Url = url,
-                                        Language = reader.GetAttribute("lang")
-                                    };
-
-                                    if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
-                                    {
-                                        info.CommunityRating = likes;
-                                    }
-
-                                    list.Add(info);
-                                }
-                                break;
-                            }
-                        default:
-                            reader.Skip();
-                            break;
+                        info.CommunityRating = likes;
                     }
                     }
+
+                    return info;
                 }
                 }
-            }
+
+                return null;
+            }).Where(i => i != null));
         }
         }
 
 
         public int Order
         public int Order
@@ -347,13 +212,17 @@ namespace MediaBrowser.Providers.Movies
             }
             }
 
 
             var id = item.GetProviderId(MetadataProviders.Tmdb);
             var id = item.GetProviderId(MetadataProviders.Tmdb);
+            if (string.IsNullOrEmpty(id))
+            {
+                id = item.GetProviderId(MetadataProviders.Imdb);
+            }
 
 
             if (!string.IsNullOrEmpty(id))
             if (!string.IsNullOrEmpty(id))
             {
             {
                 // Process images
                 // Process images
-                var xmlPath = GetFanartXmlPath(id);
+                var path = GetFanartJsonPath(id);
 
 
-                var fileInfo = new FileInfo(xmlPath);
+                var fileInfo = new FileInfo(path);
 
 
                 return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
                 return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
             }
             }
@@ -364,12 +233,12 @@ namespace MediaBrowser.Providers.Movies
         /// <summary>
         /// <summary>
         /// Gets the movie data path.
         /// Gets the movie data path.
         /// </summary>
         /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        /// <param name="tmdbId">The TMDB id.</param>
+        /// <param name="appPaths">The application paths.</param>
+        /// <param name="id">The identifier.</param>
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
-        internal static string GetMovieDataPath(IApplicationPaths appPaths, string tmdbId)
+        internal static string GetMovieDataPath(IApplicationPaths appPaths, string id)
         {
         {
-            var dataPath = Path.Combine(GetMoviesDataPath(appPaths), tmdbId);
+            var dataPath = Path.Combine(GetMoviesDataPath(appPaths), id);
 
 
             return dataPath;
             return dataPath;
         }
         }
@@ -386,27 +255,27 @@ namespace MediaBrowser.Providers.Movies
             return dataPath;
             return dataPath;
         }
         }
 
 
-        public string GetFanartXmlPath(string tmdbId)
+        public string GetFanartJsonPath(string id)
         {
         {
-            var movieDataPath = GetMovieDataPath(_config.ApplicationPaths, tmdbId);
-            return Path.Combine(movieDataPath, "fanart.xml");
+            var movieDataPath = GetMovieDataPath(_config.ApplicationPaths, id);
+            return Path.Combine(movieDataPath, "fanart.json");
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Downloads the movie XML.
+        /// Downloads the movie json.
         /// </summary>
         /// </summary>
-        /// <param name="tmdbId">The TMDB id.</param>
+        /// <param name="id">The identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        internal async Task DownloadMovieXml(string tmdbId, CancellationToken cancellationToken)
+        internal async Task DownloadMovieJson(string id, CancellationToken cancellationToken)
         {
         {
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, tmdbId);
+            var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, id);
 
 
-            var xmlPath = GetFanartXmlPath(tmdbId);
+            var path = GetFanartJsonPath(id);
 
 
-            Directory.CreateDirectory(Path.GetDirectoryName(xmlPath));
+            Directory.CreateDirectory(Path.GetDirectoryName(path));
 
 
             using (var response = await _httpClient.Get(new HttpRequestOptions
             using (var response = await _httpClient.Get(new HttpRequestOptions
             {
             {
@@ -416,17 +285,17 @@ namespace MediaBrowser.Providers.Movies
 
 
             }).ConfigureAwait(false))
             }).ConfigureAwait(false))
             {
             {
-                using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+                using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
                 {
                 {
-                    await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
+                    await response.CopyToAsync(fileStream).ConfigureAwait(false);
                 }
                 }
             }
             }
         }
         }
 
 
         private readonly Task _cachedTask = Task.FromResult(true);
         private readonly Task _cachedTask = Task.FromResult(true);
-        internal Task EnsureMovieXml(string tmdbId, CancellationToken cancellationToken)
+        internal Task EnsureMovieJson(string id, CancellationToken cancellationToken)
         {
         {
-            var path = GetFanartXmlPath(tmdbId);
+            var path = GetFanartJsonPath(id);
 
 
             var fileInfo = _fileSystem.GetFileSystemInfo(path);
             var fileInfo = _fileSystem.GetFileSystemInfo(path);
 
 
@@ -438,7 +307,31 @@ namespace MediaBrowser.Providers.Movies
                 }
                 }
             }
             }
 
 
-            return DownloadMovieXml(tmdbId, cancellationToken);
+            return DownloadMovieJson(id, cancellationToken);
+        }
+
+        public class Image
+        {
+            public string id { get; set; }
+            public string url { get; set; }
+            public string lang { get; set; }
+            public string likes { get; set; }
+        }
+
+        public class RootObject
+        {
+            public string name { get; set; }
+            public string tmdb_id { get; set; }
+            public string imdb_id { get; set; }
+            public List<Image> hdmovielogo { get; set; }
+            public List<Image> moviedisc { get; set; }
+            public List<Image> movielogo { get; set; }
+            public List<Image> movieposter { get; set; }
+            public List<Image> hdmovieclearart { get; set; }
+            public List<Image> movieart { get; set; }
+            public List<Image> moviebackground { get; set; }
+            public List<Image> moviebanner { get; set; }
+            public List<Image> moviethumb { get; set; }
         }
         }
     }
     }
 }
 }

+ 3 - 5
MediaBrowser.Providers/Music/MusicVideoMetadataService.cs

@@ -1,15 +1,13 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Providers.Manager;
 using MediaBrowser.Providers.Manager;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
+using System.Linq;
 
 
 namespace MediaBrowser.Providers.Music
 namespace MediaBrowser.Providers.Music
 {
 {
@@ -36,9 +34,9 @@ namespace MediaBrowser.Providers.Music
                 target.Album = source.Album;
                 target.Album = source.Album;
             }
             }
 
 
-            if (replaceData || string.IsNullOrEmpty(target.Artist))
+            if (replaceData || target.Artists.Count == 0)
             {
             {
-                target.Artist = source.Artist;
+                target.Artists = source.Artists.ToList();
             }
             }
         }
         }
     }
     }

+ 55 - 129
MediaBrowser.Providers/TV/FanArtSeasonProvider.cs

@@ -7,16 +7,15 @@ using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Providers;
 using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Serialization;
 using MediaBrowser.Providers.Music;
 using MediaBrowser.Providers.Music;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
-using System.Text;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using System.Xml;
 
 
 namespace MediaBrowser.Providers.TV
 namespace MediaBrowser.Providers.TV
 {
 {
@@ -26,12 +25,14 @@ namespace MediaBrowser.Providers.TV
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly IHttpClient _httpClient;
         private readonly IHttpClient _httpClient;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
+        private readonly IJsonSerializer _json;
 
 
-        public FanArtSeasonProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
+        public FanArtSeasonProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json)
         {
         {
             _config = config;
             _config = config;
             _httpClient = httpClient;
             _httpClient = httpClient;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
+            _json = json;
         }
         }
 
 
         public string Name
         public string Name
@@ -71,14 +72,14 @@ namespace MediaBrowser.Providers.TV
 
 
                 if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
                 if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
                 {
                 {
-                    await FanartSeriesProvider.Current.EnsureSeriesXml(id, cancellationToken).ConfigureAwait(false);
+                    await FanartSeriesProvider.Current.EnsureSeriesJson(id, cancellationToken).ConfigureAwait(false);
 
 
-                    var xmlPath = FanartSeriesProvider.Current.GetFanartXmlPath(id);
+                    var path = FanartSeriesProvider.Current.GetFanartJsonPath(id);
 
 
                     try
                     try
                     {
                     {
                         int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
                         int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
-                        AddImages(list, seasonNumber, xmlPath, cancellationToken);
+                        AddImages(list, seasonNumber, path, cancellationToken);
                     }
                     }
                     catch (FileNotFoundException)
                     catch (FileNotFoundException)
                     {
                     {
@@ -125,142 +126,67 @@ namespace MediaBrowser.Providers.TV
             return seasonNumber;
             return seasonNumber;
         }
         }
 
 
-        private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
+        private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string path, CancellationToken cancellationToken)
         {
         {
-            using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
-            {
-                // Use XmlReader for best performance
-                using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
-                {
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true,
-                    ValidationType = ValidationType.None
-                }))
-                {
-                    reader.MoveToContent();
+            var root = _json.DeserializeFromFile<FanartSeriesProvider.RootObject>(path);
 
 
-                    // Loop through each element
-                    while (reader.Read())
-                    {
-                        cancellationToken.ThrowIfCancellationRequested();
-
-                        if (reader.NodeType == XmlNodeType.Element)
-                        {
-                            switch (reader.Name)
-                            {
-                                case "series":
-                                    {
-                                        using (var subReader = reader.ReadSubtree())
-                                        {
-                                            AddImages(list, subReader, seasonNumber, cancellationToken);
-                                        }
-                                        break;
-                                    }
-
-                                default:
-                                    reader.Skip();
-                                    break;
-                            }
-                        }
-                    }
-                }
-            }
+            AddImages(list, root, seasonNumber, cancellationToken);
         }
         }
 
 
-        private void AddImages(List<RemoteImageInfo> list, XmlReader reader, int seasonNumber, CancellationToken cancellationToken)
+        private void AddImages(List<RemoteImageInfo> list, FanartSeriesProvider.RootObject obj, int seasonNumber, CancellationToken cancellationToken)
         {
         {
-            reader.MoveToContent();
-
-            while (reader.Read())
-            {
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        case "seasonthumbs":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 500, 281, seasonNumber);
-                                }
-                                break;
-                            }
-                        case "showbackgrounds":
-                            {
-                                using (var subReader = reader.ReadSubtree())
-                                {
-                                    PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080, seasonNumber);
-                                }
-                                break;
-                            }
-                        default:
-                            {
-                                using (reader.ReadSubtree())
-                                {
-                                }
-                                break;
-                            }
-                    }
-                }
-            }
+            PopulateImages(list, obj.seasonthumb, ImageType.Thumb, 500, 281, seasonNumber);
+            PopulateImages(list, obj.showbackground, ImageType.Backdrop, 1920, 1080, seasonNumber);
         }
         }
 
 
-        private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height, int seasonNumber)
+        private void PopulateImages(List<RemoteImageInfo> list,
+            List<FanartSeriesProvider.Image> images,
+            ImageType type,
+            int width,
+            int height,
+            int seasonNumber)
         {
         {
-            reader.MoveToContent();
+            if (images == null)
+            {
+                return;
+            }
 
 
-            while (reader.Read())
+            list.AddRange(images.Select(i =>
             {
             {
-                cancellationToken.ThrowIfCancellationRequested();
+                var url = i.url;
+                var season = i.season;
 
 
-                if (reader.NodeType == XmlNodeType.Element)
+                int imageSeasonNumber;
+
+                if (!string.IsNullOrEmpty(url) &&
+                    !string.IsNullOrEmpty(season) &&
+                    int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
+                    seasonNumber == imageSeasonNumber)
                 {
                 {
-                    switch (reader.Name)
+                    var likesString = i.likes;
+                    int likes;
+
+                    var info = new RemoteImageInfo
+                    {
+                        RatingType = RatingType.Likes,
+                        Type = type,
+                        Width = width,
+                        Height = height,
+                        ProviderName = Name,
+                        Url = url,
+                        Language = i.lang
+                    };
+
+                    if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
                     {
                     {
-                        case "seasonthumb":
-                        case "showbackground":
-                            {
-                                var url = reader.GetAttribute("url");
-                                var season = reader.GetAttribute("season");
-
-                                int imageSeasonNumber;
-
-                                if (!string.IsNullOrEmpty(url) &&
-                                    !string.IsNullOrEmpty(season) &&
-                                    int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
-                                    seasonNumber == imageSeasonNumber)
-                                {
-                                    var likesString = reader.GetAttribute("likes");
-                                    int likes;
-
-                                    var info = new RemoteImageInfo
-                                    {
-                                        RatingType = RatingType.Likes,
-                                        Type = type,
-                                        Width = width,
-                                        Height = height,
-                                        ProviderName = Name,
-                                        Url = url,
-                                        Language = reader.GetAttribute("lang")
-                                    };
-
-                                    if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
-                                    {
-                                        info.CommunityRating = likes;
-                                    }
-
-                                    list.Add(info);
-                                }
-
-                                break;
-                            }
-                        default:
-                            reader.Skip();
-                            break;
+                        info.CommunityRating = likes;
                     }
                     }
+
+                    return info;
                 }
                 }
-            }
+
+                return null;
+            }).Where(i => i != null));
         }
         }
 
 
         public int Order
         public int Order
@@ -298,9 +224,9 @@ namespace MediaBrowser.Providers.TV
             if (!String.IsNullOrEmpty(tvdbId))
             if (!String.IsNullOrEmpty(tvdbId))
             {
             {
                 // Process images
                 // Process images
-                var imagesXmlPath = FanartSeriesProvider.Current.GetFanartXmlPath(tvdbId);
+                var imagesFilePath = FanartSeriesProvider.Current.GetFanartJsonPath(tvdbId);
 
 
-                var fileInfo = new FileInfo(imagesXmlPath);
+                var fileInfo = new FileInfo(imagesFilePath);
 
 
                 return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
                 return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
             }
             }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است