ソースを参照

Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser

tikuf 11 年 前
コミット
241be6dd93
100 ファイル変更2706 行追加915 行削除
  1. 5 9
      MediaBrowser.Api/AppThemeService.cs
  2. 15 0
      MediaBrowser.Api/BaseApiService.cs
  3. 2 4
      MediaBrowser.Api/ChannelService.cs
  4. 5 10
      MediaBrowser.Api/ConfigurationService.cs
  5. 2 4
      MediaBrowser.Api/DisplayPreferencesService.cs
  6. 90 0
      MediaBrowser.Api/DlnaService.cs
  7. 5 10
      MediaBrowser.Api/EnvironmentService.cs
  8. 6 9
      MediaBrowser.Api/GamesService.cs
  9. 0 10
      MediaBrowser.Api/Images/ImageService.cs
  10. 11 1
      MediaBrowser.Api/Library/LibraryService.cs
  11. 24 48
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  12. 1 1
      MediaBrowser.Api/MediaBrowser.Api.csproj
  13. 2 4
      MediaBrowser.Api/Movies/MoviesService.cs
  14. 1 2
      MediaBrowser.Api/Movies/TrailersService.cs
  15. 4 8
      MediaBrowser.Api/Music/InstantMixService.cs
  16. 219 56
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  17. 3 3
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  18. 2 2
      MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
  19. 2 1
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  20. 19 18
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  21. 45 93
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  22. 7 1
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  23. 3 0
      MediaBrowser.Api/Playback/StreamRequest.cs
  24. 14 0
      MediaBrowser.Api/Playback/StreamState.cs
  25. 6 11
      MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
  26. 2 3
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  27. 2 5
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  28. 5 14
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  29. 1 1
      MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
  30. 0 1
      MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
  31. 16 6
      MediaBrowser.Controller/Dlna/CodecProfile.cs
  32. 4 0
      MediaBrowser.Controller/Dlna/ContainerProfile.cs
  33. 8 3
      MediaBrowser.Controller/Dlna/DeviceIdentification.cs
  34. 175 24
      MediaBrowser.Controller/Dlna/DeviceProfile.cs
  35. 7 0
      MediaBrowser.Controller/Dlna/DirectPlayProfile.cs
  36. 38 5
      MediaBrowser.Controller/Dlna/IDlnaManager.cs
  37. 16 0
      MediaBrowser.Controller/Dlna/MediaProfile.cs
  38. 25 2
      MediaBrowser.Controller/Dlna/TranscodingProfile.cs
  39. 13 6
      MediaBrowser.Controller/Entities/Trailer.cs
  40. 1 4
      MediaBrowser.Controller/Entities/User.cs
  41. 2 0
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  42. 18 3
      MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
  43. 20 0
      MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs
  44. 13 3
      MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs
  45. 15 17
      MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
  46. 0 88
      MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
  47. 26 0
      MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
  48. 8 0
      MediaBrowser.Controller/Session/ISessionController.cs
  49. 279 11
      MediaBrowser.Dlna/DlnaManager.cs
  50. 23 4
      MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
  51. 1 13
      MediaBrowser.Dlna/PlayTo/CurrentIdEventArgs.cs
  52. 17 9
      MediaBrowser.Dlna/PlayTo/Device.cs
  53. 9 16
      MediaBrowser.Dlna/PlayTo/DeviceInfo.cs
  54. 44 41
      MediaBrowser.Dlna/PlayTo/DidlBuilder.cs
  55. 45 20
      MediaBrowser.Dlna/PlayTo/DlnaController.cs
  56. 0 31
      MediaBrowser.Dlna/PlayTo/DlnaControllerFactory.cs
  57. 25 35
      MediaBrowser.Dlna/PlayTo/PlayToManager.cs
  58. 2 2
      MediaBrowser.Dlna/PlayTo/PlaylistItem.cs
  59. 15 22
      MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
  60. 25 15
      MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
  61. 2 9
      MediaBrowser.Dlna/PlayTo/StreamHelper.cs
  62. 5 19
      MediaBrowser.Dlna/Profiles/DefaultProfile.cs
  63. 3 1
      MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
  64. 31 0
      MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
  65. 6 4
      MediaBrowser.Dlna/Profiles/LgTvProfile.cs
  66. 3 1
      MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
  67. 20 18
      MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
  68. 16 7
      MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
  69. 7 3
      MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
  70. 8 4
      MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs
  71. 10 19
      MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs
  72. 10 19
      MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs
  73. 7 16
      MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs
  74. 6 15
      MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs
  75. 8 6
      MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
  76. 4 2
      MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
  77. 8 20
      MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
  78. 3 1
      MediaBrowser.Dlna/Profiles/XboxOneProfile.cs
  79. 35 0
      MediaBrowser.Dlna/Profiles/Xml/Default.xml
  80. 39 0
      MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
  81. 73 0
      MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
  82. 39 0
      MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
  83. 66 0
      MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
  84. 102 0
      MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
  85. 19 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
  86. 21 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
  87. 100 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
  88. 103 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
  89. 86 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
  90. 86 0
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
  91. 94 0
      MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
  92. 80 0
      MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
  93. 103 0
      MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
  94. 41 0
      MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
  95. 41 0
      MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
  96. 1 1
      MediaBrowser.Dlna/Server/Headers.cs
  97. 0 16
      MediaBrowser.Dlna/Server/RawHeaders.cs
  98. 3 3
      MediaBrowser.Dlna/Server/SsdpHandler.cs
  99. 23 21
      MediaBrowser.Dlna/Ssdp/SsdpHelper.cs
  100. 1 1
      MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs

+ 5 - 9
MediaBrowser.Api/AppThemeService.cs

@@ -9,16 +9,14 @@ using System.Linq;
 
 namespace MediaBrowser.Api
 {
-    [Route("/Themes", "GET")]
-    [Api(Description = "Gets a list of available themes for an app")]
+    [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
     public class GetAppThemes : IReturn<List<AppThemeInfo>>
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string App { get; set; }
     }
 
-    [Route("/Themes/Info", "GET")]
-    [Api(Description = "Gets an app theme")]
+    [Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
     public class GetAppTheme : IReturn<AppTheme>
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -28,8 +26,7 @@ namespace MediaBrowser.Api
         public string Name { get; set; }
     }
 
-    [Route("/Themes/Images", "GET")]
-    [Api(Description = "Gets an app theme")]
+    [Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
     public class GetAppThemeImage
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -45,12 +42,11 @@ namespace MediaBrowser.Api
         public string CacheTag { get; set; }
     }
 
-    [Route("/Themes", "POST")]
-    [Api(Description = "Saves a theme")]
+    [Route("/Themes", "POST", Summary = "Saves a theme")]
     public class SaveTheme : AppTheme, IReturnVoid
     {
     }
-    
+
     public class AppThemeService : BaseApiService
     {
         private readonly IAppThemeManager _themeManager;

+ 15 - 0
MediaBrowser.Api/BaseApiService.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Logging;
 using ServiceStack.Web;
 using System;
@@ -78,6 +79,20 @@ namespace MediaBrowser.Api
             return ToOptimizedResult(result);
         }
 
+        /// <summary>
+        /// Gets the session.
+        /// </summary>
+        /// <param name="sessionManager">The session manager.</param>
+        /// <returns>SessionInfo.</returns>
+        protected SessionInfo GetSession(ISessionManager sessionManager)
+        {
+            var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
+
+            return sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
+                string.Equals(i.Client, auth.Client) &&
+                string.Equals(i.ApplicationVersion, auth.Version));
+        }
+
         /// <summary>
         /// To the cached result.
         /// </summary>

+ 2 - 4
MediaBrowser.Api/ChannelService.cs

@@ -7,8 +7,7 @@ using System.Threading;
 
 namespace MediaBrowser.Api
 {
-    [Route("/Channels", "GET")]
-    [Api(("Gets available channels"))]
+    [Route("/Channels", "GET", Summary = "Gets available channels")]
     public class GetChannels : IReturn<QueryResult<BaseItemDto>>
     {
         public string UserId { get; set; }
@@ -18,8 +17,7 @@ namespace MediaBrowser.Api
         public int? Limit { get; set; }
     }
 
-    [Route("/Channels/{Id}/Items", "GET")]
-    [Api(("Gets channel items"))]
+    [Route("/Channels/{Id}/Items", "GET", Summary = "Gets channel items")]
     public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>
     {
         public string Id { get; set; }

+ 5 - 10
MediaBrowser.Api/ConfigurationService.cs

@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetConfiguration
     /// </summary>
-    [Route("/System/Configuration", "GET")]
-    [Api(("Gets application configuration"))]
+    [Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
     public class GetConfiguration : IReturn<ServerConfiguration>
     {
 
@@ -27,28 +26,24 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class UpdateConfiguration
     /// </summary>
-    [Route("/System/Configuration", "POST")]
-    [Api(("Updates application configuration"))]
+    [Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
     public class UpdateConfiguration : ServerConfiguration, IReturnVoid
     {
     }
 
-    [Route("/System/Configuration/MetadataOptions/Default", "GET")]
-    [Api(("Gets a default MetadataOptions object"))]
+    [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
     public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
     {
 
     }
 
-    [Route("/System/Configuration/MetadataPlugins", "GET")]
-    [Api(("Gets all available metadata plugins"))]
+    [Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
     public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
     {
 
     }
 
-    [Route("/System/Configuration/VideoImageExtraction", "POST")]
-    [Api(("Updates image extraction for all types"))]
+    [Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")]
     public class UpdateVideoImageExtraction : IReturnVoid
     {
         public bool Enabled { get; set; }

+ 2 - 4
MediaBrowser.Api/DisplayPreferencesService.cs

@@ -12,8 +12,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class UpdateDisplayPreferences
     /// </summary>
-    [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST")]
-    [Api(("Updates a user's display preferences for an item"))]
+    [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")]
     public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
     {
         /// <summary>
@@ -30,8 +29,7 @@ namespace MediaBrowser.Api
         public string Client { get; set; }
     }
 
-    [Route("/DisplayPreferences/{Id}", "GET")]
-    [Api(("Gets a user's display preferences for an item"))]
+    [Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]
     public class GetDisplayPreferences : IReturn<DisplayPreferences>
     {
         /// <summary>

+ 90 - 0
MediaBrowser.Api/DlnaService.cs

@@ -0,0 +1,90 @@
+using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Model.Dlna;
+using ServiceStack;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Api
+{
+    [Route("/Dlna/ProfileInfos", "GET", Summary = "Gets a list of profiles")]
+    public class GetProfileInfos : IReturn<List<DeviceProfileInfo>>
+    {
+    }
+
+    [Route("/Dlna/Profiles/{Id}", "DELETE", Summary = "Deletes a profile")]
+    public class DeleteProfile : IReturnVoid
+    {
+        [ApiMember(Name = "Id", Description = "Profile Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+        public string Id { get; set; }
+    }
+
+    [Route("/Dlna/Profiles/Default", "GET", Summary = "Gets the default profile")]
+    public class GetDefaultProfile : IReturn<DeviceProfile>
+    {
+    }
+
+    [Route("/Dlna/Profiles/{Id}", "GET", Summary = "Gets a single profile")]
+    public class GetProfile : IReturn<DeviceProfile>
+    {
+        [ApiMember(Name = "Id", Description = "Profile Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+        public string Id { get; set; }
+    }
+
+    [Route("/Dlna/Profiles/{ProfileId}", "POST", Summary = "Updates a profile")]
+    public class UpdateProfile : DeviceProfile, IReturnVoid
+    {
+        [ApiMember(Name = "ProfileId", Description = "Profile Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+        public string ProfileId { get; set; }
+    }
+
+    [Route("/Dlna/Profiles", "POST", Summary = "Creates a profile")]
+    public class CreateProfile : DeviceProfile, IReturnVoid
+    {
+    }
+
+    public class DlnaService : BaseApiService
+    {
+        private readonly IDlnaManager _dlnaManager;
+
+        public DlnaService(IDlnaManager dlnaManager)
+        {
+            _dlnaManager = dlnaManager;
+        }
+
+        public object Get(GetProfileInfos request)
+        {
+            var result = _dlnaManager.GetProfileInfos().ToList();
+
+            return ToOptimizedResult(result);
+        }
+
+        public object Get(GetProfile request)
+        {
+            var result = _dlnaManager.GetProfile(request.Id);
+
+            return ToOptimizedResult(result);
+        }
+
+        public object Get(GetDefaultProfile request)
+        {
+            var result = _dlnaManager.GetDefaultProfile();
+
+            return ToOptimizedResult(result);
+        }
+
+        public void Delete(DeleteProfile request)
+        {
+            _dlnaManager.DeleteProfile(request.Id);
+        }
+
+        public void Post(UpdateProfile request)
+        {
+            _dlnaManager.UpdateProfile(request);
+        }
+
+        public void Post(CreateProfile request)
+        {
+            _dlnaManager.CreateProfile(request);
+        }
+    }
+}

+ 5 - 10
MediaBrowser.Api/EnvironmentService.cs

@@ -13,8 +13,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetDirectoryContents
     /// </summary>
-    [Route("/Environment/DirectoryContents", "GET")]
-    [Api(Description = "Gets the contents of a given directory in the file system")]
+    [Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")]
     public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
     {
         /// <summary>
@@ -46,8 +45,7 @@ namespace MediaBrowser.Api
         public bool IncludeHidden { get; set; }
     }
 
-    [Route("/Environment/NetworkShares", "GET")]
-    [Api(Description = "Gets shares from a network device")]
+    [Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
     public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
     {
         /// <summary>
@@ -61,8 +59,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetDrives
     /// </summary>
-    [Route("/Environment/Drives", "GET")]
-    [Api(Description = "Gets available drives from the server's file system")]
+    [Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")]
     public class GetDrives : IReturn<List<FileSystemEntryInfo>>
     {
     }
@@ -70,14 +67,12 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetNetworkComputers
     /// </summary>
-    [Route("/Environment/NetworkDevices", "GET")]
-    [Api(Description = "Gets a list of devices on the network")]
+    [Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")]
     public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
     {
     }
 
-    [Route("/Environment/ParentPath", "GET")]
-    [Api(Description = "Gets the parent path of a given path")]
+    [Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")]
     public class GetParentPath : IReturn<string>
     {
         /// <summary>

+ 6 - 9
MediaBrowser.Api/GamesService.cs

@@ -1,5 +1,4 @@
-using System.Globalization;
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
@@ -7,6 +6,7 @@ using MediaBrowser.Model.Dto;
 using ServiceStack;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 
@@ -15,8 +15,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetSimilarGames
     /// </summary>
-    [Route("/Games/{Id}/Similar", "GET")]
-    [Api(Description = "Finds games similar to a given game.")]
+    [Route("/Games/{Id}/Similar", "GET", Summary = "Finds games similar to a given game.")]
     public class GetSimilarGames : BaseGetSimilarItemsFromItem
     {
     }
@@ -24,8 +23,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetGameSystemSummaries
     /// </summary>
-    [Route("/Games/SystemSummaries", "GET")]
-    [Api(Description = "Finds games similar to a given game.")]
+    [Route("/Games/SystemSummaries", "GET", Summary = "Finds games similar to a given game.")]
     public class GetGameSystemSummaries : IReturn<List<GameSystemSummary>>
     {
         /// <summary>
@@ -39,8 +37,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetGameSystemSummaries
     /// </summary>
-    [Route("/Games/PlayerIndex", "GET")]
-    [Api(Description = "Gets an index of players (1-x) and the number of games listed under each")]
+    [Route("/Games/PlayerIndex", "GET", Summary = "Gets an index of players (1-x) and the number of games listed under each")]
     public class GetPlayerIndex : IReturn<List<ItemIndex>>
     {
         /// <summary>
@@ -117,7 +114,7 @@ namespace MediaBrowser.Api
         }
 
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-        
+
         public object Get(GetPlayerIndex request)
         {
             var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager)

+ 0 - 10
MediaBrowser.Api/Images/ImageService.cs

@@ -15,7 +15,6 @@ using ServiceStack.Text.Controller;
 using ServiceStack.Web;
 using System;
 using System.Collections.Generic;
-using System.Drawing;
 using System.IO;
 using System.Linq;
 using System.Threading;
@@ -776,15 +775,6 @@ namespace MediaBrowser.Api.Images
 
                 var bytes = Convert.FromBase64String(text);
 
-                // Validate first
-                using (var validationStream = new MemoryStream(bytes))
-                {
-                    // This will throw an exception if it's not a valid image
-                    using (Image.FromStream(validationStream))
-                    {
-                    }
-                }
-
                 var memoryStream = new MemoryStream(bytes)
                 {
                     Position = 0

+ 11 - 1
MediaBrowser.Api/Library/LibraryService.cs

@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
@@ -245,12 +246,13 @@ namespace MediaBrowser.Api.Library
 
         private readonly IDtoService _dtoService;
         private readonly IChannelManager _channelManager;
+        private readonly ISessionManager _sessionManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// </summary>
         public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
-                              IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager)
+                              IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager, ISessionManager sessionManager)
         {
             _itemRepo = itemRepo;
             _libraryManager = libraryManager;
@@ -258,6 +260,7 @@ namespace MediaBrowser.Api.Library
             _dtoService = dtoService;
             _userDataManager = userDataManager;
             _channelManager = channelManager;
+            _sessionManager = sessionManager;
         }
 
         public object Get(GetMediaFolders request)
@@ -504,6 +507,13 @@ namespace MediaBrowser.Api.Library
         {
             var item = _dtoService.GetItemByDtoId(request.Id);
 
+            var session = GetSession(_sessionManager);
+
+            if (!session.UserId.HasValue || !_userManager.GetUserById(session.UserId.Value).Configuration.EnableContentDeletion)
+            {
+                throw new UnauthorizedAccessException("This operation requires a logged in user with delete access.");
+            }
+            
             return _libraryManager.DeleteItem(item);
         }
 

+ 24 - 48
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -12,14 +12,12 @@ using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.LiveTv
 {
-    [Route("/LiveTv/Info", "GET")]
-    [Api(Description = "Gets available live tv services.")]
+    [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
     public class GetLiveTvInfo : IReturn<LiveTvInfo>
     {
     }
 
-    [Route("/LiveTv/Channels", "GET")]
-    [Api(Description = "Gets available live tv channels.")]
+    [Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
     public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>
     {
         [ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -43,8 +41,7 @@ namespace MediaBrowser.Api.LiveTv
         public int? Limit { get; set; }
     }
 
-    [Route("/LiveTv/Channels/{Id}", "GET")]
-    [Api(Description = "Gets a live tv channel")]
+    [Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
     public class GetChannel : IReturn<ChannelInfoDto>
     {
         /// <summary>
@@ -58,8 +55,7 @@ namespace MediaBrowser.Api.LiveTv
         public string UserId { get; set; }
     }
 
-    [Route("/LiveTv/Recordings", "GET")]
-    [Api(Description = "Gets live tv recordings")]
+    [Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
     public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
     {
         [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -87,16 +83,14 @@ namespace MediaBrowser.Api.LiveTv
         public string SeriesTimerId { get; set; }
     }
 
-    [Route("/LiveTv/Recordings/Groups", "GET")]
-    [Api(Description = "Gets live tv recording groups")]
+    [Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
     public class GetRecordingGroups : IReturn<QueryResult<RecordingGroupDto>>
     {
         [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string UserId { get; set; }
     }
 
-    [Route("/LiveTv/Recordings/{Id}", "GET")]
-    [Api(Description = "Gets a live tv recording")]
+    [Route("/LiveTv/Recordings/{Id}", "GET", Summary = "Gets a live tv recording")]
     public class GetRecording : IReturn<RecordingInfoDto>
     {
         [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -106,32 +100,28 @@ namespace MediaBrowser.Api.LiveTv
         public string UserId { get; set; }
     }
 
-    [Route("/LiveTv/Tuners/{Id}/Reset", "POST")]
-    [Api(Description = "Resets a tv tuner")]
+    [Route("/LiveTv/Tuners/{Id}/Reset", "POST", Summary = "Resets a tv tuner")]
     public class ResetTuner : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Tuner Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/Timers/{Id}", "GET")]
-    [Api(Description = "Gets a live tv timer")]
+    [Route("/LiveTv/Timers/{Id}", "GET", Summary = "Gets a live tv timer")]
     public class GetTimer : IReturn<TimerInfoDto>
     {
         [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/Timers/Defaults", "GET")]
-    [Api(Description = "Gets default values for a new timer")]
+    [Route("/LiveTv/Timers/Defaults", "GET", Summary = "Gets default values for a new timer")]
     public class GetDefaultTimer : IReturn<SeriesTimerInfoDto>
     {
         [ApiMember(Name = "ProgramId", Description = "Optional, to attach default values based on a program.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ProgramId { get; set; }
     }
 
-    [Route("/LiveTv/Timers", "GET")]
-    [Api(Description = "Gets live tv timers")]
+    [Route("/LiveTv/Timers", "GET", Summary = "Gets live tv timers")]
     public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
     {
         [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -141,8 +131,7 @@ namespace MediaBrowser.Api.LiveTv
         public string SeriesTimerId { get; set; }
     }
 
-    [Route("/LiveTv/Programs", "GET,POST")]
-    [Api(Description = "Gets available live tv epgs..")]
+    [Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
     public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
     {
         [ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
@@ -164,8 +153,7 @@ namespace MediaBrowser.Api.LiveTv
         public string MaxEndDate { get; set; }
     }
 
-    [Route("/LiveTv/Programs/Recommended", "GET")]
-    [Api(Description = "Gets available live tv epgs..")]
+    [Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
     public class GetRecommendedPrograms : IReturn<QueryResult<ProgramInfoDto>>
     {
         [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
@@ -181,8 +169,7 @@ namespace MediaBrowser.Api.LiveTv
         public bool? HasAired { get; set; }
     }
 
-    [Route("/LiveTv/Programs/{Id}", "GET")]
-    [Api(Description = "Gets a live tv program")]
+    [Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
     public class GetProgram : IReturn<ProgramInfoDto>
     {
         [ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -193,44 +180,38 @@ namespace MediaBrowser.Api.LiveTv
     }
 
 
-    [Route("/LiveTv/Recordings/{Id}", "DELETE")]
-    [Api(Description = "Deletes a live tv recording")]
+    [Route("/LiveTv/Recordings/{Id}", "DELETE", Summary = "Deletes a live tv recording")]
     public class DeleteRecording : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/Timers/{Id}", "DELETE")]
-    [Api(Description = "Cancels a live tv timer")]
+    [Route("/LiveTv/Timers/{Id}", "DELETE", Summary = "Cancels a live tv timer")]
     public class CancelTimer : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/Timers/{Id}", "POST")]
-    [Api(Description = "Updates a live tv timer")]
+    [Route("/LiveTv/Timers/{Id}", "POST", Summary = "Updates a live tv timer")]
     public class UpdateTimer : TimerInfoDto, IReturnVoid
     {
     }
 
-    [Route("/LiveTv/Timers", "POST")]
-    [Api(Description = "Creates a live tv timer")]
+    [Route("/LiveTv/Timers", "POST", Summary = "Creates a live tv timer")]
     public class CreateTimer : TimerInfoDto, IReturnVoid
     {
     }
 
-    [Route("/LiveTv/SeriesTimers/{Id}", "GET")]
-    [Api(Description = "Gets a live tv series timer")]
+    [Route("/LiveTv/SeriesTimers/{Id}", "GET", Summary = "Gets a live tv series timer")]
     public class GetSeriesTimer : IReturn<TimerInfoDto>
     {
         [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/SeriesTimers", "GET")]
-    [Api(Description = "Gets live tv series timers")]
+    [Route("/LiveTv/SeriesTimers", "GET", Summary = "Gets live tv series timers")]
     public class GetSeriesTimers : IReturn<QueryResult<SeriesTimerInfoDto>>
     {
         [ApiMember(Name = "SortBy", Description = "Optional. Sort by SortName or Priority", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
@@ -240,36 +221,31 @@ namespace MediaBrowser.Api.LiveTv
         public SortOrder SortOrder { get; set; }
     }
 
-    [Route("/LiveTv/SeriesTimers/{Id}", "DELETE")]
-    [Api(Description = "Cancels a live tv series timer")]
+    [Route("/LiveTv/SeriesTimers/{Id}", "DELETE", Summary = "Cancels a live tv series timer")]
     public class CancelSeriesTimer : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/SeriesTimers/{Id}", "POST")]
-    [Api(Description = "Updates a live tv series timer")]
+    [Route("/LiveTv/SeriesTimers/{Id}", "POST", Summary = "Updates a live tv series timer")]
     public class UpdateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
     {
     }
 
-    [Route("/LiveTv/SeriesTimers", "POST")]
-    [Api(Description = "Creates a live tv series timer")]
+    [Route("/LiveTv/SeriesTimers", "POST", Summary = "Creates a live tv series timer")]
     public class CreateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
     {
     }
 
-    [Route("/LiveTv/Recordings/Groups/{Id}", "GET")]
-    [Api(Description = "Gets a recording group")]
+    [Route("/LiveTv/Recordings/Groups/{Id}", "GET", Summary = "Gets a recording group")]
     public class GetRecordingGroup : IReturn<RecordingGroupDto>
     {
         [ApiMember(Name = "Id", Description = "Recording group Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
     }
 
-    [Route("/LiveTv/GuideInfo", "GET")]
-    [Api(Description = "Gets guide info")]
+    [Route("/LiveTv/GuideInfo", "GET", Summary = "Gets guide info")]
     public class GetGuideInfo : IReturn<GuideInfo>
     {
     }

+ 1 - 1
MediaBrowser.Api/MediaBrowser.Api.csproj

@@ -53,7 +53,6 @@
     <Reference Include="System.Core" />
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Data" />
-    <Reference Include="System.Drawing" />
     <Reference Include="System.Xml" />
     <Reference Include="ServiceStack.Interfaces">
       <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
@@ -67,6 +66,7 @@
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     <Compile Include="ChannelService.cs" />
+    <Compile Include="DlnaService.cs" />
     <Compile Include="Movies\CollectionService.cs" />
     <Compile Include="Music\AlbumsService.cs" />
     <Compile Include="AppThemeService.cs" />

+ 2 - 4
MediaBrowser.Api/Movies/MoviesService.cs

@@ -17,8 +17,7 @@ namespace MediaBrowser.Api.Movies
     /// <summary>
     /// Class GetSimilarMovies
     /// </summary>
-    [Route("/Movies/{Id}/Similar", "GET")]
-    [Api(Description = "Finds movies and trailers similar to a given movie.")]
+    [Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
     public class GetSimilarMovies : BaseGetSimilarItemsFromItem
     {
         [ApiMember(Name = "IncludeTrailers", Description = "Whether or not to include trailers within the results. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -30,8 +29,7 @@ namespace MediaBrowser.Api.Movies
         }
     }
 
-    [Route("/Movies/Recommendations", "GET")]
-    [Api(Description = "Gets movie recommendations")]
+    [Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
     public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
     {
         [ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]

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

@@ -10,8 +10,7 @@ namespace MediaBrowser.Api.Movies
     /// <summary>
     /// Class GetSimilarTrailers
     /// </summary>
-    [Route("/Trailers/{Id}/Similar", "GET")]
-    [Api(Description = "Finds movies and trailers similar to a given trailer.")]
+    [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
     public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
     {
     }

+ 4 - 8
MediaBrowser.Api/Music/InstantMixService.cs

@@ -9,28 +9,24 @@ using System.Linq;
 
 namespace MediaBrowser.Api.Music
 {
-    [Route("/Songs/{Id}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given song")]
+    [Route("/Songs/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given song")]
     public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
     {
     }
 
-    [Route("/Albums/{Id}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given album")]
+    [Route("/Albums/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given album")]
     public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
     {
     }
 
-    [Route("/Artists/{Name}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given artist")]
+    [Route("/Artists/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
     public class GetInstantMixFromArtist : BaseGetSimilarItems
     {
         [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Name { get; set; }
     }
 
-    [Route("/MusicGenres/{Name}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a music genre")]
+    [Route("/MusicGenres/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
     public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
     {
         [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]

+ 219 - 56
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -65,6 +66,7 @@ namespace MediaBrowser.Api.Playback
 
         protected IItemRepository ItemRepository { get; private set; }
         protected ILiveTvManager LiveTvManager { get; private set; }
+        protected IDlnaManager DlnaManager { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
@@ -77,8 +79,9 @@ namespace MediaBrowser.Api.Playback
         /// <param name="dtoService">The dto service.</param>
         /// <param name="fileSystem">The file system.</param>
         /// <param name="itemRepository">The item repository.</param>
-        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager)
+        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
         {
+            DlnaManager = dlnaManager;
             EncodingManager = encodingManager;
             LiveTvManager = liveTvManager;
             ItemRepository = itemRepository;
@@ -313,6 +316,7 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <param name="state">The state.</param>
         /// <param name="videoCodec">The video codec.</param>
+        /// <param name="isHls">if set to <c>true</c> [is HLS].</param>
         /// <returns>System.String.</returns>
         protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
         {
@@ -337,20 +341,17 @@ namespace MediaBrowser.Api.Playback
                         break;
                 }
 
-                if (!isHls)
+                switch (qualitySetting)
                 {
-                    switch (qualitySetting)
-                    {
-                        case EncodingQuality.HighSpeed:
-                            param += " -crf 23";
-                            break;
-                        case EncodingQuality.HighQuality:
-                            param += " -crf 20";
-                            break;
-                        case EncodingQuality.MaxQuality:
-                            param += " -crf 18";
-                            break;
-                    }
+                    case EncodingQuality.HighSpeed:
+                        param += " -crf 23";
+                        break;
+                    case EncodingQuality.HighQuality:
+                        param += " -crf 20";
+                        break;
+                    case EncodingQuality.MaxQuality:
+                        param += " -crf 18";
+                        break;
                 }
             }
 
@@ -502,14 +503,13 @@ namespace MediaBrowser.Api.Playback
                 return string.Format("{4} -vf \"{0}scale=trunc({1}/2)*2:trunc({2}/2)*2{3}\"", yadifParam, widthParam, heightParam, assSubtitleParam, copyTsParam);
             }
 
-            // If Max dimensions were supplied
-            //this makes my brain hurt. For width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
+            // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
             if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
             {
-                var MaxwidthParam = request.MaxWidth.Value.ToString(UsCulture);
-                var MaxheightParam = request.MaxHeight.Value.ToString(UsCulture);
+                var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
+                var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
 
-                return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, MaxwidthParam, MaxheightParam, assSubtitleParam, copyTsParam);
+                return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, maxWidthParam, maxHeightParam, assSubtitleParam, copyTsParam);
             }
 
             var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
@@ -774,29 +774,24 @@ namespace MediaBrowser.Api.Playback
         {
             var codec = request.AudioCodec;
 
-            if (!string.IsNullOrEmpty(codec))
+            if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
             {
-                if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "aac -strict experimental";
-                }
-                if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "libmp3lame";
-                }
-                if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "libvorbis";
-                }
-                if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "wmav2";
-                }
-
-                return codec.ToLower();
+                return "aac -strict experimental";
+            }
+            if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
+            {
+                return "libmp3lame";
+            }
+            if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
+            {
+                return "libvorbis";
+            }
+            if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
+            {
+                return "wmav2";
             }
 
-            return "copy";
+            return codec.ToLower();
         }
 
         /// <summary>
@@ -972,8 +967,6 @@ namespace MediaBrowser.Api.Playback
 
         private async void StreamToStandardInput(Process process, StreamState state)
         {
-            state.StandardInputCancellationTokenSource = new CancellationTokenSource();
-
             try
             {
                 await StreamToStandardInputInternal(process, state).ConfigureAwait(false);
@@ -1034,11 +1027,6 @@ namespace MediaBrowser.Api.Playback
             {
                 var hasFixedResolution = state.VideoRequest.HasFixedResolution;
 
-                if (isHls)
-                {
-                    return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
-                }
-
                 if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
                 {
                     if (hasFixedResolution)
@@ -1049,7 +1037,6 @@ namespace MediaBrowser.Api.Playback
                     // With vpx when crf is used, b:v becomes a max rate
                     // https://trac.ffmpeg.org/wiki/vpxEncodingGuide
                     return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
-                    //return string.Format(" -minrate:v ({0}*.95) -maxrate:v ({0}*1.05) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture));
                 }
 
                 if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
@@ -1057,13 +1044,17 @@ namespace MediaBrowser.Api.Playback
                     return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
                 }
 
-
                 // H264
                 if (hasFixedResolution)
                 {
+                    if (isHls)
+                    {
+                        return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
+                    }
+
                     return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
                 }
-
+                
                 return string.Format(" -maxrate {0} -bufsize {1}",
                     bitrate.Value.ToString(UsCulture),
                     (bitrate.Value * 2).ToString(UsCulture));
@@ -1212,7 +1203,7 @@ namespace MediaBrowser.Api.Playback
 
                 if (i == 0)
                 {
-                    // Device profile name
+                    request.DeviceProfileId = val;
                 }
                 else if (i == 1)
                 {
@@ -1270,35 +1261,35 @@ namespace MediaBrowser.Api.Playback
                 {
                     if (videoRequest != null)
                     {
-                        videoRequest.MaxWidth = int.Parse(val, UsCulture);
+                        videoRequest.MaxFramerate = double.Parse(val, UsCulture);
                     }
                 }
                 else if (i == 12)
                 {
                     if (videoRequest != null)
                     {
-                        videoRequest.MaxHeight = int.Parse(val, UsCulture);
+                        videoRequest.MaxWidth = int.Parse(val, UsCulture);
                     }
                 }
                 else if (i == 13)
                 {
                     if (videoRequest != null)
                     {
-                        videoRequest.Framerate = int.Parse(val, UsCulture);
+                        videoRequest.MaxHeight = int.Parse(val, UsCulture);
                     }
                 }
                 else if (i == 14)
                 {
                     if (videoRequest != null)
                     {
-                        request.StartTimeTicks = long.Parse(val, UsCulture);
+                        videoRequest.Framerate = int.Parse(val, UsCulture);
                     }
                 }
                 else if (i == 15)
                 {
                     if (videoRequest != null)
                     {
-                        videoRequest.Profile = val;
+                        request.StartTimeTicks = long.Parse(val, UsCulture);
                     }
                 }
                 else if (i == 16)
@@ -1487,9 +1478,181 @@ namespace MediaBrowser.Api.Playback
             state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
             state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
 
+            ApplyDeviceProfileSettings(state);
+
             return state;
         }
 
+        private void ApplyDeviceProfileSettings(StreamState state)
+        {
+            var headers = new Dictionary<string, string>();
+
+            foreach (var key in Request.Headers.AllKeys)
+            {
+                headers[key] = Request.Headers[key];
+            }
+
+            var profile = string.IsNullOrWhiteSpace(state.Request.DeviceProfileId) ?
+                DlnaManager.GetProfile(headers) :
+                DlnaManager.GetProfile(state.Request.DeviceProfileId);
+
+            if (profile == null)
+            {
+                // Don't use settings from the default profile. 
+                // Only use a specific profile if it was requested.
+                return;
+            }
+
+            var container = Path.GetExtension(state.RequestedUrl);
+
+            if (string.IsNullOrEmpty(container))
+            {
+                container = Path.GetExtension(GetOutputFilePath(state));
+            }
+
+            var audioCodec = state.Request.AudioCodec;
+
+            if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.AudioStream != null)
+            {
+                audioCodec = state.AudioStream.Codec;
+            }
+
+            var videoCodec = state.VideoRequest == null ? null : state.VideoRequest.VideoCodec;
+
+            if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.VideoStream != null)
+            {
+                videoCodec = state.VideoStream.Codec;
+            }
+
+            var mediaProfile = state.VideoRequest == null ?
+                profile.GetAudioMediaProfile(container, audioCodec, state.AudioStream) :
+                profile.GetVideoMediaProfile(container, audioCodec, videoCodec, state.AudioStream, state.VideoStream);
+
+            if (mediaProfile != null)
+            {
+                state.MimeType = mediaProfile.MimeType;
+                state.OrgPn = mediaProfile.OrgPn;
+            }
+
+            var transcodingProfile = state.VideoRequest == null ?
+                profile.GetAudioTranscodingProfile(container, audioCodec) :
+                profile.GetVideoTranscodingProfile(container, audioCodec, videoCodec);
+
+            if (transcodingProfile != null)
+            {
+                state.EstimateContentLength = transcodingProfile.EstimateContentLength;
+                state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
+                state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
+
+                foreach (var setting in transcodingProfile.Settings)
+                {
+                    switch (setting.Name)
+                    {
+                        case TranscodingSettingType.VideoProfile:
+                        {
+                            if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile))
+                            {
+                                state.VideoRequest.Profile = setting.Value;
+                            }
+                            break;
+                        }
+                        default:
+                            throw new ArgumentException("Unrecognized TranscodingSettingType");
+                    }
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Adds the dlna headers.
+        /// </summary>
+        /// <param name="state">The state.</param>
+        /// <param name="responseHeaders">The response headers.</param>
+        /// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param>
+        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
+        protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
+        {
+            var timeSeek = GetHeader("TimeSeekRange.dlna.org");
+
+            if (!string.IsNullOrEmpty(timeSeek))
+            {
+                ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
+                return;
+            }
+
+            var transferMode = GetHeader("transferMode.dlna.org");
+            responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
+            responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
+
+            var contentFeatures = string.Empty;
+            var extension = GetOutputFileExtension(state);
+
+            // 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
+            var orgOp = isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00";
+
+            // 0 = native, 1 = transcoded
+            var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
+
+            const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
+
+            if (!string.IsNullOrWhiteSpace(state.OrgPn))
+            {
+                contentFeatures = "DLNA.ORG_PN=" + state.OrgPn;
+            }
+            else if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=MP3";
+            }
+            else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=AAC_ISO";
+            }
+            else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=WMABASE";
+            }
+            else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=AVI";
+            }
+            else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=MATROSKA";
+            }
+            else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
+            }
+            else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
+            }
+            else if (string.Equals(extension, ".ts", StringComparison.OrdinalIgnoreCase))
+            {
+                contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
+            }
+            //else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
+            //{
+            //    contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
+            //}
+            //else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
+            //{
+            //    // ??
+            //    contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
+            //}
+
+            if (!string.IsNullOrEmpty(contentFeatures))
+            {
+                responseHeaders["contentFeatures.dlna.org"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+            }
+
+            foreach (var item in responseHeaders)
+            {
+                Request.Response.AddHeader(item.Key, item.Value);
+            }
+        }
+
         /// <summary>
         /// Enforces the resolution limit.
         /// </summary>
@@ -1605,7 +1768,7 @@ namespace MediaBrowser.Api.Playback
                 return "vorbis";
             }
 
-            return null;
+            return "copy";
         }
 
         /// <summary>

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

@@ -2,13 +2,13 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.IO;
 using System;
 using System.Collections.Generic;
@@ -24,7 +24,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public abstract class BaseHlsService : BaseStreamingService
     {
-        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
+        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
         {
         }
 
@@ -200,7 +200,7 @@ namespace MediaBrowser.Api.Playback.Hls
             builder.AppendLine("#EXTM3U");
 
             // Pad a little to satisfy the apple hls validator
-            var paddedBitrate = Convert.ToInt32(bitrate * 1.05);
+            var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
 
             // Main stream
             builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));

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

@@ -1,12 +1,12 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.IO;
 using ServiceStack;
 using System;
@@ -60,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class DynamicHlsService : BaseHlsService
     {
-        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
+        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
         {
         }
 

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

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
@@ -52,7 +53,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public class VideoHlsService : BaseHlsService
     {
-        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
+        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
         {
         }
 

+ 19 - 18
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
@@ -16,23 +17,22 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// <summary>
     /// Class GetAudioStream
     /// </summary>
-    [Route("/Audio/{Id}/stream.mp3", "GET")]
-    [Route("/Audio/{Id}/stream.wma", "GET")]
-    [Route("/Audio/{Id}/stream.aac", "GET")]
-    [Route("/Audio/{Id}/stream.flac", "GET")]
-    [Route("/Audio/{Id}/stream.ogg", "GET")]
-    [Route("/Audio/{Id}/stream.oga", "GET")]
-    [Route("/Audio/{Id}/stream.webm", "GET")]
-    [Route("/Audio/{Id}/stream", "GET")]
-    [Route("/Audio/{Id}/stream.mp3", "HEAD")]
-    [Route("/Audio/{Id}/stream.wma", "HEAD")]
-    [Route("/Audio/{Id}/stream.aac", "HEAD")]
-    [Route("/Audio/{Id}/stream.flac", "HEAD")]
-    [Route("/Audio/{Id}/stream.ogg", "HEAD")]
-    [Route("/Audio/{Id}/stream.oga", "HEAD")]
-    [Route("/Audio/{Id}/stream.webm", "HEAD")]
-    [Route("/Audio/{Id}/stream", "HEAD")]
-    [Api(Description = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.mp3", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.wma", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.aac", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.flac", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.ogg", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.oga", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.webm", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream", "GET", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.mp3", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.wma", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.aac", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.flac", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.ogg", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.oga", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream.webm", "HEAD", Summary = "Gets an audio stream")]
+    [Route("/Audio/{Id}/stream", "HEAD", Summary = "Gets an audio stream")]
     public class GetAudioStream : StreamRequest
     {
 
@@ -43,7 +43,8 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class AudioService : BaseProgressiveStreamingService
     {
-        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, httpClient, imageProcessor)
+        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
+            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
         {
         }
 

+ 45 - 93
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -1,13 +1,13 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.IO;
 using ServiceStack.Web;
 using System;
@@ -26,8 +26,8 @@ namespace MediaBrowser.Api.Playback.Progressive
         protected readonly IImageProcessor ImageProcessor;
         protected readonly IHttpClient HttpClient;
 
-        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor)
-            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
+        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
+            : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
         {
             HttpClient = httpClient;
             ImageProcessor = imageProcessor;
@@ -100,92 +100,6 @@ namespace MediaBrowser.Api.Playback.Progressive
             return null;
         }
 
-        /// <summary>
-        /// Adds the dlna headers.
-        /// </summary>
-        /// <param name="state">The state.</param>
-        /// <param name="responseHeaders">The response headers.</param>
-        /// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        private void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
-        {
-            var timeSeek = GetHeader("TimeSeekRange.dlna.org");
-
-            if (!string.IsNullOrEmpty(timeSeek))
-            {
-                ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
-                return;
-            }
-
-            var transferMode = GetHeader("transferMode.dlna.org");
-            responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
-            responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
-
-            var contentFeatures = string.Empty;
-            var extension = GetOutputFileExtension(state);
-
-            // 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
-            var orgOp = isStaticallyStreamed ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00";
-
-            // 0 = native, 1 = transcoded
-            var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
-
-            const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
-
-            if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=MP3";
-            }
-            else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=AAC_ISO";
-            }
-            else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=WMABASE";
-            }
-            else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=AVI";
-            }
-            else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=MATROSKA";
-            }
-            else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
-            }
-            else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
-            }
-            else if (string.Equals(extension, ".ts", StringComparison.OrdinalIgnoreCase))
-            {
-                contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
-            }
-            //else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
-            //{
-            //    contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
-            //}
-            //else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
-            //{
-            //    // ??
-            //    contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
-            //}
-
-
-            if (!string.IsNullOrEmpty(contentFeatures))
-            {
-                responseHeaders["contentFeatures.dlna.org"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
-            }
-
-            foreach (var item in responseHeaders)
-            {
-                Request.Response.AddHeader(item.Key, item.Value);
-            }
-        }
-
         /// <summary>
         /// Gets the type of the transcoding job.
         /// </summary>
@@ -303,18 +217,30 @@ namespace MediaBrowser.Api.Playback.Progressive
 
             var contentType = state.GetMimeType(outputPath);
 
+            var contentLength = state.EstimateContentLength ? GetEstimatedContentLength(state) : null;
+
+            if (contentLength.HasValue)
+            {
+                responseHeaders["Content-Length"] = contentLength.Value.ToString(UsCulture);
+            }
+
             // Headers only
             if (isHeadRequest)
             {
                 var streamResult = ResultFactory.GetResult(new byte[] { }, contentType, responseHeaders);
-                var hasOptions = streamResult as IHasOptions;
-                if (hasOptions != null)
+
+                if (!contentLength.HasValue)
                 {
-                    if (hasOptions.Options.ContainsKey("Content-Length"))
+                    var hasOptions = streamResult as IHasOptions;
+                    if (hasOptions != null)
                     {
-                        hasOptions.Options.Remove("Content-Length");
+                        if (hasOptions.Options.ContainsKey("Content-Length"))
+                        {
+                            hasOptions.Options.Remove("Content-Length");
+                        }
                     }
                 }
+
                 return streamResult;
             }
 
@@ -339,5 +265,31 @@ namespace MediaBrowser.Api.Playback.Progressive
 
             return result;
         }
+
+        /// <summary>
+        /// Gets the length of the estimated content.
+        /// </summary>
+        /// <param name="state">The state.</param>
+        /// <returns>System.Nullable{System.Int64}.</returns>
+        private long? GetEstimatedContentLength(StreamState state)
+        {
+            var totalBitrate = 0;
+
+            if (state.Request.AudioBitRate.HasValue)
+            {
+                totalBitrate += state.Request.AudioBitRate.Value;
+            }
+            if (state.VideoRequest != null && state.VideoRequest.VideoBitRate.HasValue)
+            {
+                totalBitrate += state.VideoRequest.VideoBitRate.Value;
+            }
+
+            if (totalBitrate > 0 && state.RunTimeTicks.HasValue)
+            {
+                return Convert.ToInt64(totalBitrate * TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds);
+            }
+
+            return null;
+        }
     }
 }

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

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Library;
@@ -58,7 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class VideoService : BaseProgressiveStreamingService
     {
-        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, httpClient, imageProcessor)
+        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
         {
         }
 
@@ -137,6 +138,11 @@ namespace MediaBrowser.Api.Playback.Progressive
                 return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
             }
 
+            if (state.EnableMpegtsM2TsMode)
+            {
+                args += " -mpegts_m2ts_mode 1";
+            }
+
             const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
 
             args += keyFrameArg;

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

@@ -65,6 +65,9 @@ namespace MediaBrowser.Api.Playback
         [ApiMember(Name = "Static", Description = "Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool Static { get; set; }
 
+        [ApiMember(Name = "DeviceProfileId", Description = "Optional. The dlna device profile id to utilize.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string DeviceProfileId { get; set; }
+        
         /// <summary>
         /// For testing purposes
         /// </summary>

+ 14 - 0
MediaBrowser.Api/Playback/StreamState.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using System.Collections.Generic;
@@ -77,8 +78,21 @@ namespace MediaBrowser.Api.Playback
 
         public string InputAudioCodec { get; set; }
 
+        public string MimeType { get; set; }
+        public string OrgPn { get; set; }
+
+        // DLNA Settings
+        public bool EstimateContentLength { get; set; }
+        public bool EnableMpegtsM2TsMode { get; set; }
+        public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
+        
         public string GetMimeType(string outputPath)
         {
+            if (!string.IsNullOrEmpty(MimeType))
+            {
+                return MimeType;
+            }
+
             return MimeTypes.GetMimeType(outputPath);
         }
     }

+ 6 - 11
MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs

@@ -2,18 +2,17 @@
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Tasks;
 using ServiceStack;
+using ServiceStack.Text.Controller;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using ServiceStack.Text.Controller;
 
 namespace MediaBrowser.Api.ScheduledTasks
 {
     /// <summary>
     /// Class GetScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/{Id}", "GET")]
-    [Api(Description = "Gets a scheduled task, by Id")]
+    [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
     public class GetScheduledTask : IReturn<TaskInfo>
     {
         /// <summary>
@@ -27,8 +26,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class GetScheduledTasks
     /// </summary>
-    [Route("/ScheduledTasks", "GET")]
-    [Api(Description = "Gets scheduled tasks")]
+    [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
     public class GetScheduledTasks : IReturn<List<TaskInfo>>
     {
         [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -38,8 +36,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class StartScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "POST")]
-    [Api(Description = "Starts a scheduled task")]
+    [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
     public class StartScheduledTask : IReturnVoid
     {
         /// <summary>
@@ -53,8 +50,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class StopScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "DELETE")]
-    [Api(Description = "Stops a scheduled task")]
+    [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
     public class StopScheduledTask : IReturnVoid
     {
         /// <summary>
@@ -68,8 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class UpdateScheduledTaskTriggers
     /// </summary>
-    [Route("/ScheduledTasks/{Id}/Triggers", "POST")]
-    [Api(Description = "Updates the triggers for a scheduled task")]
+    [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
     public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
     {
         /// <summary>

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

@@ -20,9 +20,8 @@ namespace MediaBrowser.Api.UserLibrary
     /// <summary>
     /// Class GetItems
     /// </summary>
-    [Route("/Items", "GET")]
-    [Route("/Users/{UserId}/Items", "GET")]
-    [Api(Description = "Gets items based on a query.")]
+    [Route("/Items", "GET", Summary = "Gets items based on a query.")]
+    [Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
     public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
     {
         /// <summary>

+ 2 - 5
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -8,15 +8,13 @@ using ServiceStack;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.UserLibrary
 {
     /// <summary>
     /// Class GetStudios
     /// </summary>
-    [Route("/Studios", "GET")]
-    [Api(Description = "Gets all studios from a given item, folder, or the entire library")]
+    [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
     public class GetStudios : GetItemsByName
     {
     }
@@ -24,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// <summary>
     /// Class GetStudio
     /// </summary>
-    [Route("/Studios/{Name}", "GET")]
-    [Api(Description = "Gets a studio, by name")]
+    [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
     public class GetStudio : IReturn<BaseItemDto>
     {
         /// <summary>

+ 5 - 14
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -705,7 +705,7 @@ namespace MediaBrowser.Api.UserLibrary
                 datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
             }
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
 
@@ -719,15 +719,6 @@ namespace MediaBrowser.Api.UserLibrary
             return dto;
         }
 
-        private SessionInfo GetSession()
-        {
-            var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
-
-            return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
-                string.Equals(i.Client, auth.Client) &&
-                string.Equals(i.ApplicationVersion, auth.Version));
-        }
-
         /// <summary>
         /// Posts the specified request.
         /// </summary>
@@ -744,7 +735,7 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 CanSeek = request.CanSeek,
                 Item = item,
-                SessionId = GetSession().Id,
+                SessionId = GetSession(_sessionManager).Id,
                 QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
                 MediaSourceId = request.MediaSourceId
             };
@@ -768,7 +759,7 @@ namespace MediaBrowser.Api.UserLibrary
                 PositionTicks = request.PositionTicks,
                 IsMuted = request.IsMuted,
                 IsPaused = request.IsPaused,
-                SessionId = GetSession().Id,
+                SessionId = GetSession(_sessionManager).Id,
                 MediaSourceId = request.MediaSourceId
             };
 
@@ -787,7 +778,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var item = _dtoService.GetItemByDtoId(request.Id, user.Id);
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var info = new PlaybackStopInfo
             {
@@ -817,7 +808,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
 

+ 1 - 1
MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs

@@ -49,7 +49,7 @@ namespace MediaBrowser.Api.WebSocket
         /// <returns>Task{SystemInfo}.</returns>
         protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
         {
-            return Task.FromResult(_sessionManager.Sessions.Select(_dtoService.GetSessionInfoDto));
+            return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_dtoService.GetSessionInfoDto));
         }
     }
 }

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

@@ -102,7 +102,6 @@
     <Compile Include="Security\PluginSecurityManager.cs" />
     <Compile Include="Serialization\JsonSerializer.cs" />
     <Compile Include="Serialization\XmlSerializer.cs" />
-    <Compile Include="Updates\ApplicationUpdater.cs" />
     <Compile Include="Updates\InstallationManager.cs" />
     <Compile Include="Security\UsageReporter.cs" />
   </ItemGroup>

+ 16 - 6
MediaBrowser.Controller/Dlna/CodecProfile.cs

@@ -1,13 +1,18 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Controller.Dlna
 {
     public class CodecProfile
     {
+        [XmlAttribute("type")]
         public CodecType Type { get; set; }
+       
         public ProfileCondition[] Conditions { get; set; }
+
+        [XmlAttribute("codec")]
         public string Codec { get; set; }
 
         public CodecProfile()
@@ -30,16 +35,23 @@ namespace MediaBrowser.Controller.Dlna
 
     public enum CodecType
     {
-        VideoCodec = 0,
-        VideoAudioCodec = 1,
-        AudioCodec = 2
+        Video = 0,
+        VideoAudio = 1,
+        Audio = 2
     }
 
     public class ProfileCondition
     {
+        [XmlAttribute("condition")]
         public ProfileConditionType Condition { get; set; }
+
+        [XmlAttribute("property")]
         public ProfileConditionValue Property { get; set; }
+
+        [XmlAttribute("value")]
         public string Value { get; set; }
+
+        [XmlAttribute("isRequired")]
         public bool IsRequired { get; set; }
 
         public ProfileCondition()
@@ -69,8 +81,6 @@ namespace MediaBrowser.Controller.Dlna
         VideoBitrate,
         VideoFramerate,
         VideoLevel,
-        VideoPacketLength,
-        VideoProfile,
-        VideoTimestamp
+        VideoProfile
     }
 }

+ 4 - 0
MediaBrowser.Controller/Dlna/ContainerProfile.cs

@@ -1,12 +1,16 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Controller.Dlna
 {
     public class ContainerProfile
     {
+        [XmlAttribute("type")]
         public DlnaProfileType Type { get; set; }
         public ProfileCondition[] Conditions { get; set; }
+
+        [XmlAttribute("container")]
         public string Container { get; set; }
 
         public ContainerProfile()

+ 8 - 3
MediaBrowser.Controller/Dlna/DeviceIdentification.cs

@@ -1,4 +1,6 @@
 
+using System.Xml.Serialization;
+
 namespace MediaBrowser.Controller.Dlna
 {
     public class DeviceIdentification
@@ -41,9 +43,7 @@ namespace MediaBrowser.Controller.Dlna
         /// <summary>
         /// Gets or sets the manufacturer.
         /// </summary>
-        /// <value>
-        /// The manufacturer.
-        /// </value>
+        /// <value>The manufacturer.</value>
         public string Manufacturer { get; set; }
         /// <summary>
         /// Gets or sets the manufacturer URL.
@@ -64,8 +64,13 @@ namespace MediaBrowser.Controller.Dlna
 
     public class HttpHeaderInfo
     {
+        [XmlAttribute("name")]
         public string Name { get; set; }
+
+        [XmlAttribute("value")]
         public string Value { get; set; }
+
+        [XmlAttribute("match")]
         public HeaderMatchType Match { get; set; }
     }
 

+ 175 - 24
MediaBrowser.Controller/Dlna/DeviceProfile.cs

@@ -1,6 +1,13 @@
-
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Serialization;
+
 namespace MediaBrowser.Controller.Dlna
 {
+    [XmlRoot("Profile")]
     public class DeviceProfile
     {
         /// <summary>
@@ -9,25 +16,11 @@ namespace MediaBrowser.Controller.Dlna
         /// <value>The name.</value>
         public string Name { get; set; }
 
-        /// <summary>
-        /// Gets or sets the type of the client.
-        /// </summary>
-        /// <value>The type of the client.</value>
-        public string ClientType { get; set; }
-
-        /// <summary>
-        /// Gets or sets the transcoding profiles.
-        /// </summary>
-        /// <value>The transcoding profiles.</value>
-        public TranscodingProfile[] TranscodingProfiles { get; set; }
-
-        /// <summary>
-        /// Gets or sets the direct play profiles.
-        /// </summary>
-        /// <value>The direct play profiles.</value>
-        public DirectPlayProfile[] DirectPlayProfiles { get; set; }
+        [XmlIgnore]
+        public string Id { get; set; }
 
-        public ContainerProfile[] ContainerProfiles { get; set; }
+        [XmlIgnore]
+        public DeviceProfileType ProfileType { get; set; }
 
         /// <summary>
         /// Gets or sets the identification.
@@ -43,7 +36,9 @@ namespace MediaBrowser.Controller.Dlna
         public string ModelNumber { get; set; }
         public string ModelUrl { get; set; }
         public bool IgnoreTranscodeByteRangeRequests { get; set; }
-        public bool SupportsAlbumArtInDidl { get; set; }
+        public bool EnableAlbumArtInDidl { get; set; }
+
+        public string SupportedMediaTypes { get; set; }
 
         /// <summary>
         /// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
@@ -60,14 +55,27 @@ namespace MediaBrowser.Controller.Dlna
 
         public string ProtocolInfo { get; set; }
 
-        public MediaProfile[] MediaProfiles { get; set; }
-        public CodecProfile[] CodecProfiles { get; set; }
-
         public int TimelineOffsetSeconds { get; set; }
-
         public bool RequiresPlainVideoItems { get; set; }
         public bool RequiresPlainFolders { get; set; }
 
+        /// <summary>
+        /// Gets or sets the direct play profiles.
+        /// </summary>
+        /// <value>The direct play profiles.</value>
+        public DirectPlayProfile[] DirectPlayProfiles { get; set; }
+
+        /// <summary>
+        /// Gets or sets the transcoding profiles.
+        /// </summary>
+        /// <value>The transcoding profiles.</value>
+        public TranscodingProfile[] TranscodingProfiles { get; set; }
+
+        public ContainerProfile[] ContainerProfiles { get; set; }
+
+        public CodecProfile[] CodecProfiles { get; set; }
+        public MediaProfile[] MediaProfiles { get; set; }
+
         public DeviceProfile()
         {
             DirectPlayProfiles = new DirectPlayProfile[] { };
@@ -75,6 +83,149 @@ namespace MediaBrowser.Controller.Dlna
             MediaProfiles = new MediaProfile[] { };
             CodecProfiles = new CodecProfile[] { };
             ContainerProfiles = new ContainerProfile[] { };
+
+            SupportedMediaTypes = "Audio,Photo,Video";
+        }
+
+        public List<string> GetSupportedMediaTypes()
+        {
+            return (SupportedMediaTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+        }
+
+        public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
+        {
+            container = (container ?? string.Empty).TrimStart('.');
+
+            return TranscodingProfiles.FirstOrDefault(i =>
+            {
+                if (i.Type != DlnaProfileType.Audio)
+                {
+                    return false;
+                }
+
+                if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
+
+                if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
+                {
+                    return false;
+                }
+
+                return true;
+            });
+        }
+
+        public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
+        {
+            container = (container ?? string.Empty).TrimStart('.');
+
+            return TranscodingProfiles.FirstOrDefault(i =>
+            {
+                if (i.Type != DlnaProfileType.Video)
+                {
+                    return false;
+                }
+
+                if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
+
+                if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
+                {
+                    return false;
+                }
+
+                if (!string.Equals(videoCodec, i.VideoCodec, StringComparison.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
+
+                return true;
+            });
+        }
+
+        public MediaProfile GetAudioMediaProfile(string container, string audioCodec, MediaStream audioStream)
+        {
+            container = (container ?? string.Empty).TrimStart('.');
+
+            return MediaProfiles.FirstOrDefault(i =>
+            {
+                if (i.Type != DlnaProfileType.Audio)
+                {
+                    return false;
+                }
+
+                var containers = i.GetContainers().ToList();
+                if (containers.Count > 0 && !containers.Contains(container))
+                {
+                    return false;
+                }
+
+                var audioCodecs = i.GetAudioCodecs().ToList();
+                if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
+                {
+                    return false;
+                }
+
+                return true;
+            });
+        }
+
+        public MediaProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, MediaStream audioStream, MediaStream videoStream)
+        {
+            container = (container ?? string.Empty).TrimStart('.');
+
+            return MediaProfiles.FirstOrDefault(i =>
+            {
+                if (i.Type != DlnaProfileType.Video)
+                {
+                    return false;
+                }
+
+                var containers = i.GetContainers().ToList();
+                if (containers.Count > 0 && !containers.Contains(container))
+                {
+                    return false;
+                }
+
+                var audioCodecs = i.GetAudioCodecs().ToList();
+                if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
+                {
+                    return false;
+                }
+
+                var videoCodecs = i.GetVideoCodecs().ToList();
+                if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty))
+                {
+                    return false;
+                }
+
+                return true;
+            });
+        }
+
+        public MediaProfile GetPhotoMediaProfile(string container)
+        {
+            container = (container ?? string.Empty).TrimStart('.');
+
+            return MediaProfiles.FirstOrDefault(i =>
+            {
+                if (i.Type != DlnaProfileType.Photo)
+                {
+                    return false;
+                }
+
+                var containers = i.GetContainers().ToList();
+                if (containers.Count > 0 && !containers.Contains(container))
+                {
+                    return false;
+                }
+
+                return true;
+            });
         }
     }
 }

+ 7 - 0
MediaBrowser.Controller/Dlna/DirectPlayProfile.cs

@@ -1,14 +1,21 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Controller.Dlna
 {
     public class DirectPlayProfile
     {
+        [XmlAttribute("container")]
         public string Container { get; set; }
+
+        [XmlAttribute("audioCodec")]
         public string AudioCodec { get; set; }
+
+        [XmlAttribute("videoCodec")]
         public string VideoCodec { get; set; }
 
+        [XmlAttribute("type")]
         public DlnaProfileType Type { get; set; }
 
         public List<string> GetContainers()

+ 38 - 5
MediaBrowser.Controller/Dlna/IDlnaManager.cs

@@ -1,21 +1,54 @@
-using System.Collections.Generic;
+using MediaBrowser.Model.Dlna;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Dlna
 {
     public interface IDlnaManager
     {
         /// <summary>
-        /// Gets the dlna profiles.
+        /// Gets the profile infos.
         /// </summary>
-        /// <returns>IEnumerable{DlnaProfile}.</returns>
-        IEnumerable<DeviceProfile> GetProfiles();
+        /// <returns>IEnumerable{DeviceProfileInfo}.</returns>
+        IEnumerable<DeviceProfileInfo> GetProfileInfos();
+
+        /// <summary>
+        /// Gets the profile.
+        /// </summary>
+        /// <param name="headers">The headers.</param>
+        /// <returns>DeviceProfile.</returns>
+        DeviceProfile GetProfile(IDictionary<string,string> headers);
 
         /// <summary>
         /// Gets the default profile.
         /// </summary>
-        /// <returns>DlnaProfile.</returns>
+        /// <returns>DeviceProfile.</returns>
         DeviceProfile GetDefaultProfile();
 
+        /// <summary>
+        /// Creates the profile.
+        /// </summary>
+        /// <param name="profile">The profile.</param>
+        void CreateProfile(DeviceProfile profile);
+        
+        /// <summary>
+        /// Updates the profile.
+        /// </summary>
+        /// <param name="profile">The profile.</param>
+        void UpdateProfile(DeviceProfile profile);
+        
+        /// <summary>
+        /// Deletes the profile.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        void DeleteProfile(string id);
+        
+        /// <summary>
+        /// Gets the profile.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <returns>DeviceProfile.</returns>
+        DeviceProfile GetProfile(string id);
+        
         /// <summary>
         /// Gets the profile.
         /// </summary>

+ 16 - 0
MediaBrowser.Controller/Dlna/MediaProfile.cs

@@ -1,16 +1,27 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Controller.Dlna
 {
     public class MediaProfile
     {
+        [XmlAttribute("container")]
         public string Container { get; set; }
+
+        [XmlAttribute("audioCodec")]
         public string AudioCodec { get; set; }
+
+        [XmlAttribute("videoCodec")]
         public string VideoCodec { get; set; }
 
+        [XmlAttribute("type")]
         public DlnaProfileType Type { get; set; }
+
+        [XmlAttribute("orgPn")]
         public string OrgPn { get; set; }
+
+        [XmlAttribute("mimeType")]
         public string MimeType { get; set; }
 
         public ProfileCondition[] Conditions { get; set; }
@@ -19,6 +30,11 @@ namespace MediaBrowser.Controller.Dlna
         {
             Conditions = new ProfileCondition[] {};
         }
+
+        public List<string> GetContainers()
+        {
+            return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+        }
         
         public List<string> GetAudioCodecs()
         {

+ 25 - 2
MediaBrowser.Controller/Dlna/TranscodingProfile.cs

@@ -1,17 +1,33 @@
-
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Serialization;
+
 namespace MediaBrowser.Controller.Dlna
 {
     public class TranscodingProfile
     {
+        [XmlAttribute("container")]
         public string Container { get; set; }
 
+        [XmlAttribute("type")]
         public DlnaProfileType Type { get; set; }
 
+        [XmlAttribute("videoCodec")]
         public string VideoCodec { get; set; }
+
+        [XmlAttribute("audioCodec")]
         public string AudioCodec { get; set; }
 
+        [XmlAttribute("protocol")]
+        public string Protocol { get; set; }
+        
+        [XmlAttribute("estimateContentLength")]
         public bool EstimateContentLength { get; set; }
 
+        [XmlAttribute("enableMpegtsM2TsMode")]
+        public bool EnableMpegtsM2TsMode { get; set; }
+
+        [XmlAttribute("transcodeSeekInfo")]
         public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
 
         public TranscodingSetting[] Settings { get; set; }
@@ -21,12 +37,19 @@ namespace MediaBrowser.Controller.Dlna
             Settings = new TranscodingSetting[] { };
         }
 
-        public bool EnableMpegtsM2TsMode { get; set; }
+
+        public List<string> GetAudioCodecs()
+        {
+            return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+        }
     }
 
     public class TranscodingSetting
     {
+        [XmlAttribute("name")]
         public TranscodingSettingType Name { get; set; }
+
+        [XmlAttribute("value")]
         public string Value { get; set; }
     }
 

+ 13 - 6
MediaBrowser.Controller/Entities/Trailer.cs

@@ -3,8 +3,9 @@ using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
-using System.Runtime.Serialization;
+using System.Globalization;
 using System.Linq;
+using System.Runtime.Serialization;
 
 namespace MediaBrowser.Controller.Entities
 {
@@ -22,7 +23,7 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         /// <value>The preferred metadata country code.</value>
         public string PreferredMetadataCountryCode { get; set; }
-        
+
         public Trailer()
         {
             RemoteTrailers = new List<MediaUrl>();
@@ -33,19 +34,19 @@ namespace MediaBrowser.Controller.Entities
         }
 
         public float? Metascore { get; set; }
-        
+
         public List<Guid> LocalTrailerIds { get; set; }
-        
+
         public List<MediaUrl> RemoteTrailers { get; set; }
 
         public List<string> Keywords { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the taglines.
         /// </summary>
         /// <value>The taglines.</value>
         public List<string> Taglines { get; set; }
-   
+
         /// <summary>
         /// Gets or sets the budget.
         /// </summary>
@@ -92,6 +93,12 @@ namespace MediaBrowser.Controller.Entities
             {
                 key = key + "-trailer";
 
+                // Make sure different trailers have their own data.
+                if (RunTimeTicks.HasValue)
+                {
+                    key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+                }
+
                 return key;
             }
 

+ 1 - 4
MediaBrowser.Controller/Entities/User.cs

@@ -121,10 +121,7 @@ namespace MediaBrowser.Controller.Entities
             {
                 _configuration = value;
 
-                if (value == null)
-                {
-                    _configurationInitialized = false;
-                }
+                _configurationInitialized = value != null;
             }
         }
 

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

@@ -157,6 +157,7 @@
     <Compile Include="Localization\ILocalizationManager.cs" />
     <Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
     <Compile Include="MediaEncoding\IEncodingManager.cs" />
+    <Compile Include="MediaEncoding\ImageEncodingOptions.cs" />
     <Compile Include="MediaEncoding\IMediaEncoder.cs" />
     <Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
     <Compile Include="Net\IHasResultFactory.cs" />
@@ -187,6 +188,7 @@
     <Compile Include="Providers\MetadataRefreshOptions.cs" />
     <Compile Include="Providers\NameParser.cs" />
     <Compile Include="Providers\MetadataStatus.cs" />
+    <Compile Include="Providers\ISeriesOrderManager.cs" />
     <Compile Include="Session\ISessionManager.cs" />
     <Compile Include="Drawing\ImageExtensions.cs" />
     <Compile Include="Entities\AggregateFolder.cs" />

+ 18 - 3
MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs

@@ -24,16 +24,23 @@ namespace MediaBrowser.Controller.MediaEncoding
         string Version { get; }
 
         /// <summary>
-        /// Extracts the image.
+        /// Extracts the audio image.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{Stream}.</returns>
+        Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Extracts the video image.
         /// </summary>
         /// <param name="inputFiles">The input files.</param>
         /// <param name="type">The type.</param>
-        /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
         /// <param name="threedFormat">The threed format.</param>
         /// <param name="offset">The offset.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{Stream}.</returns>
-        Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+        Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
         
         /// <summary>
         /// Extracts the text subtitle.
@@ -81,6 +88,14 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <param name="type">The type.</param>
         /// <returns>System.String.</returns>
         string GetInputArgument(string[] inputFiles, InputType type);
+
+        /// <summary>
+        /// Encodes the image.
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{Stream}.</returns>
+        Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken);
     }
 
     /// <summary>

+ 20 - 0
MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs

@@ -0,0 +1,20 @@
+
+namespace MediaBrowser.Controller.MediaEncoding
+{
+    public class ImageEncodingOptions
+    {
+        public string InputPath { get; set; }
+        
+        public int? Width { get; set; }
+
+        public int? Height { get; set; }
+
+        public int? MaxWidth { get; set; }
+
+        public int? MaxHeight { get; set; }
+
+        public int? Quality { get; set; }
+        
+        public string Format { get; set; }
+    }
+}

+ 13 - 3
MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.MediaEncoding
 {
@@ -24,7 +23,18 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// Gets or sets the chapters.
         /// </summary>
         /// <value>The chapters.</value>
-        public List<ChapterInfo> Chapters { get; set; }
+        public MediaChapter[] Chapters { get; set; }
+    }
+
+    public class MediaChapter
+    {
+        public int id { get; set; }
+        public string time_base { get; set; }
+        public long start { get; set; }
+        public string start_time { get; set; }
+        public long end { get; set; }
+        public string end_time { get; set; }
+        public Dictionary<string, string> tags { get; set; }
     }
 
     /// <summary>

+ 15 - 17
MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs

@@ -154,7 +154,8 @@ namespace MediaBrowser.Controller.MediaEncoding
                 Codec = streamInfo.codec_name,
                 Profile = streamInfo.profile,
                 Level = streamInfo.level,
-                Index = streamInfo.index
+                Index = streamInfo.index,
+                PixelFormat = streamInfo.pix_fmt
             };
 
             if (streamInfo.tags != null)
@@ -196,24 +197,21 @@ namespace MediaBrowser.Controller.MediaEncoding
             }
 
             // Get stream bitrate
-            if (stream.Type != MediaStreamType.Subtitle)
-            {
-                var bitrate = 0;
+            var bitrate = 0;
 
-                if (!string.IsNullOrEmpty(streamInfo.bit_rate))
-                {
-                    bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
-                }
-                else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate))
-                {
-                    // If the stream info doesn't have a bitrate get the value from the media format info
-                    bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
-                }
+            if (!string.IsNullOrEmpty(streamInfo.bit_rate))
+            {
+                bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
+            }
+            else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video)
+            {
+                // If the stream info doesn't have a bitrate get the value from the media format info
+                bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
+            }
 
-                if (bitrate > 0)
-                {
-                    stream.BitRate = bitrate;
-                }
+            if (bitrate > 0)
+            {
+                stream.BitRate = bitrate;
             }
 
             if (streamInfo.disposition != null)

+ 0 - 88
MediaBrowser.Controller/Providers/BaseItemXmlParser.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
@@ -284,22 +283,6 @@ namespace MediaBrowser.Controller.Providers
                         break;
                     }
 
-                case "TagLine":
-                    {
-                        var tagline = reader.ReadElementContentAsString();
-
-                        var hasTaglines = item as IHasTaglines;
-                        if (hasTaglines != null)
-                        {
-                            if (!string.IsNullOrWhiteSpace(tagline))
-                            {
-                                hasTaglines.AddTagline(tagline);
-                            }
-                        }
-
-                        break;
-                    }
-
                 case "Language":
                     {
                         var val = reader.ReadElementContentAsString();
@@ -380,9 +363,7 @@ namespace MediaBrowser.Controller.Providers
                     }
 
                 case "ContentRating":
-                case "certification":
                 case "MPAARating":
-                case "ESRBRating":
                     {
                         var rating = reader.ReadElementContentAsString();
 
@@ -415,7 +396,6 @@ namespace MediaBrowser.Controller.Providers
                         break;
                     }
 
-                case "Runtime":
                 case "RunningTime":
                     {
                         var text = reader.ReadElementContentAsString();
@@ -431,19 +411,6 @@ namespace MediaBrowser.Controller.Providers
                         break;
                     }
 
-                case "Genre":
-                    {
-                        foreach (var name in SplitNames(reader.ReadElementContentAsString()))
-                        {
-                            if (string.IsNullOrWhiteSpace(name))
-                            {
-                                continue;
-                            }
-                            item.AddGenre(name);
-                        }
-                        break;
-                    }
-
                 case "AspectRatio":
                     {
                         var val = reader.ReadElementContentAsString();
@@ -587,7 +554,6 @@ namespace MediaBrowser.Controller.Providers
                         break;
                     }
 
-                case "ReleaseYear":
                 case "ProductionYear":
                     {
                         var val = reader.ReadElementContentAsString();
@@ -606,7 +572,6 @@ namespace MediaBrowser.Controller.Providers
 
                 case "Rating":
                 case "IMDBrating":
-                case "TGDBRating":
                     {
 
                         var rating = reader.ReadElementContentAsString();
@@ -683,22 +648,6 @@ namespace MediaBrowser.Controller.Providers
                         }
                         break;
                     }
-                case "MusicbrainzId":
-                    {
-                        var mbz = reader.ReadElementContentAsString();
-                        if (!string.IsNullOrWhiteSpace(mbz))
-                        {
-                            if (item is MusicAlbum)
-                            {
-                                item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz);
-                            }
-                            else if (item is MusicArtist)
-                            {
-                                item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz);
-                            }
-                        }
-                        break;
-                    }
                 case "MusicBrainzAlbumId":
                     {
                         var mbz = reader.ReadElementContentAsString();
@@ -802,9 +751,7 @@ namespace MediaBrowser.Controller.Providers
                     }
                     break;
 
-                case "IMDB_ID":
                 case "IMDB":
-                case "IMDbId":
                     var imDbId = reader.ReadElementContentAsString();
                     if (!string.IsNullOrWhiteSpace(imDbId))
                     {
@@ -856,15 +803,6 @@ namespace MediaBrowser.Controller.Providers
                         break;
                     }
 
-                case "ParentalRating":
-                    {
-                        using (var subtree = reader.ReadSubtree())
-                        {
-                            FetchFromParentalRatingNode(subtree, item);
-                        }
-                        break;
-                    }
-
                 case "Studios":
                     {
                         using (var subtree = reader.ReadSubtree())
@@ -1227,32 +1165,6 @@ namespace MediaBrowser.Controller.Providers
             }
         }
 
-        /// <summary>
-        /// Fetches from parental rating node.
-        /// </summary>
-        /// <param name="reader">The reader.</param>
-        /// <param name="item">The item.</param>
-        private void FetchFromParentalRatingNode(XmlReader reader, T item)
-        {
-            reader.MoveToContent();
-
-            while (reader.Read())
-            {
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        // Removed support for "Value" tag as it conflicted with MPAA rating but leaving this function for possible
-                        // future support of "Description" -ebr
-
-                        default:
-                            reader.Skip();
-                            break;
-                    }
-                }
-            }
-        }
-
         /// <summary>
         /// Gets the persons from XML node.
         /// </summary>

+ 26 - 0
MediaBrowser.Controller/Providers/ISeriesOrderManager.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MediaBrowser.Common;
+
+namespace MediaBrowser.Controller.Providers
+{
+    public interface ISeriesOrderProvider
+    {
+        string OrderType { get; }
+        Task<int?> FindSeriesIndex(string seriesName);
+    }
+
+    public static class SeriesOrderTypes
+    {
+        public const string Anime = "Anime";
+    }
+
+    public interface ISeriesOrderManager
+    {
+        Task<int?> FindSeriesIndex(string orderType, string seriesName);
+        void AddParts(IEnumerable<ISeriesOrderProvider> orderProviders);
+    }
+}

+ 8 - 0
MediaBrowser.Controller/Session/ISessionController.cs

@@ -59,6 +59,14 @@ namespace MediaBrowser.Controller.Session
         /// <returns>Task.</returns>
         Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// Sends the generic command.
+        /// </summary>
+        /// <param name="command">The command.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken);
+        
         /// <summary>
         /// Sends the library update info.
         /// </summary>

+ 279 - 11
MediaBrowser.Dlna/DlnaManager.cs

@@ -1,9 +1,14 @@
 using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Dlna.Profiles;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
+using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
 
@@ -11,21 +16,36 @@ namespace MediaBrowser.Dlna
 {
     public class DlnaManager : IDlnaManager
     {
-        private IApplicationPaths _appPaths;
+        private readonly IApplicationPaths _appPaths;
         private readonly IXmlSerializer _xmlSerializer;
         private readonly IFileSystem _fileSystem;
-        private readonly IJsonSerializer _jsonSerializer;
+        private readonly ILogger _logger;
 
-        public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
+        public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IApplicationPaths appPaths, ILogger logger)
         {
             _xmlSerializer = xmlSerializer;
             _fileSystem = fileSystem;
-            _jsonSerializer = jsonSerializer;
+            _appPaths = appPaths;
+            _logger = logger;
 
-            GetProfiles();
+            //DumpProfiles();
         }
 
         public IEnumerable<DeviceProfile> GetProfiles()
+        {
+            ExtractProfilesIfNeeded();
+
+            var list = GetProfiles(UserProfilesPath, DeviceProfileType.User)
+                .OrderBy(i => i.Name)
+                .ToList();
+
+            list.AddRange(GetProfiles(SystemProfilesPath, DeviceProfileType.System)
+                .OrderBy(i => i.Name));
+
+            return list;
+        }
+
+        private void DumpProfiles()
         {
             var list = new List<DeviceProfile>
             {
@@ -43,27 +63,72 @@ namespace MediaBrowser.Dlna
                 new WdtvLiveProfile(),
                 new DenonAvrProfile(),
                 new LinksysDMA2100Profile(),
-                new LgTvProfile()
+                new LgTvProfile(),
+                new Foobar2000Profile(),
+                new DefaultProfile()
             };
 
             foreach (var item in list)
             {
-                //_xmlSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".xml");
-                //_jsonSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".json");
+                var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
+
+                _xmlSerializer.SerializeToFile(item, path);
             }
+        }
 
-            return list;
+        private bool _extracted;
+        private readonly object _syncLock = new object();
+        private void ExtractProfilesIfNeeded()
+        {
+            if (!_extracted)
+            {
+                lock (_syncLock)
+                {
+                    if (!_extracted)
+                    {
+                        try
+                        {
+                            ExtractSystemProfiles();
+                        }
+                        catch (Exception ex)
+                        {
+                            _logger.ErrorException("Error extracting DLNA profiles.", ex);
+                        }
+
+                        _extracted = true;
+                    }
+
+                }
+            }
         }
 
         public DeviceProfile GetDefaultProfile()
         {
+            ExtractProfilesIfNeeded();
+
             return new DefaultProfile();
         }
 
         public DeviceProfile GetProfile(DeviceIdentification deviceInfo)
         {
-            return GetProfiles().FirstOrDefault(i => IsMatch(deviceInfo, i.Identification)) ??
-                GetDefaultProfile();
+            if (deviceInfo == null)
+            {
+                throw new ArgumentNullException("deviceInfo");
+            }
+
+            var profile = GetProfiles()
+                .FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification));
+
+            if (profile != null)
+            {
+                _logger.Debug("Found matching device profile: {0}", profile.Name);
+            }
+            else
+            {
+                _logger.Debug("No matching device profile found. The default will need to be used.");
+            }
+
+            return profile;
         }
 
         private bool IsMatch(DeviceIdentification deviceInfo, DeviceIdentification profileInfo)
@@ -124,5 +189,208 @@ namespace MediaBrowser.Dlna
 
             return true;
         }
+
+        public DeviceProfile GetProfile(IDictionary<string, string> headers)
+        {
+            if (headers == null)
+            {
+                throw new ArgumentNullException("headers");
+            }
+
+            return GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
+        }
+
+        private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)
+        {
+            return profileInfo.Headers.Any(i => IsMatch(headers, i));
+        }
+
+        private bool IsMatch(IDictionary<string, string> headers, HttpHeaderInfo header)
+        {
+            string value;
+
+            if (headers.TryGetValue(header.Name, out value))
+            {
+                switch (header.Match)
+                {
+                    case HeaderMatchType.Equals:
+                        return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
+                    case HeaderMatchType.Substring:
+                        return value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
+                    case HeaderMatchType.Regex:
+                        return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase);
+                    default:
+                        throw new ArgumentException("Unrecognized HeaderMatchType");
+                }
+            }
+
+            return false;
+        }
+
+        private string UserProfilesPath
+        {
+            get
+            {
+                return Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user");
+            }
+        }
+
+        private string SystemProfilesPath
+        {
+            get
+            {
+                return Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system");
+            }
+        }
+
+        private IEnumerable<DeviceProfile> GetProfiles(string path, DeviceProfileType type)
+        {
+            try
+            {
+                return new DirectoryInfo(path)
+                    .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+                    .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
+                    .Select(i => ParseProfileXmlFile(i.FullName, type))
+                    .Where(i => i != null)
+                    .ToList();
+            }
+            catch (DirectoryNotFoundException)
+            {
+                return new List<DeviceProfile>();
+            }
+        }
+
+        private DeviceProfile ParseProfileXmlFile(string path, DeviceProfileType type)
+        {
+            try
+            {
+                var profile = (DeviceProfile)_xmlSerializer.DeserializeFromFile(typeof(DeviceProfile), path);
+
+                profile.Id = path.ToLower().GetMD5().ToString("N");
+                profile.ProfileType = type;
+
+                return profile;
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error parsing profile xml: {0}", ex, path);
+
+                return null;
+            }
+        }
+
+        public DeviceProfile GetProfile(string id)
+        {
+            if (string.IsNullOrWhiteSpace(id))
+            {
+                throw new ArgumentNullException("id");
+            }
+
+            var info = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, id));
+
+            return ParseProfileXmlFile(info.Path, info.Info.Type);
+        }
+
+        private IEnumerable<InternalProfileInfo> GetProfileInfosInternal()
+        {
+            ExtractProfilesIfNeeded();
+
+            return GetProfileInfos(UserProfilesPath, DeviceProfileType.User)
+                .Concat(GetProfileInfos(SystemProfilesPath, DeviceProfileType.System))
+                .OrderBy(i => i.Info.Type == DeviceProfileType.User ? 0 : 1)
+                .ThenBy(i => i.Info.Name);
+        }
+
+        public IEnumerable<DeviceProfileInfo> GetProfileInfos()
+        {
+            return GetProfileInfosInternal().Select(i => i.Info);
+        }
+
+        private IEnumerable<InternalProfileInfo> GetProfileInfos(string path, DeviceProfileType type)
+        {
+            try
+            {
+                return new DirectoryInfo(path)
+                    .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+                    .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
+                    .Select(i => new InternalProfileInfo
+                    {
+                        Path = i.FullName,
+
+                        Info = new DeviceProfileInfo
+                        {
+                            Id = i.FullName.ToLower().GetMD5().ToString("N"),
+                            Name = Path.GetFileNameWithoutExtension(i.FullName),
+                            Type = type
+                        }
+                    })
+                    .ToList();
+            }
+            catch (DirectoryNotFoundException)
+            {
+                return new List<InternalProfileInfo>();
+            }
+        }
+
+        private void ExtractSystemProfiles()
+        {
+            var assembly = GetType().Assembly;
+            var namespaceName = GetType().Namespace + ".Profiles.Xml.";
+
+            var systemProfilesPath = SystemProfilesPath;
+
+            foreach (var name in assembly.GetManifestResourceNames()
+                .Where(i => i.StartsWith(namespaceName))
+                .ToList())
+            {
+                var filename = Path.GetFileName(name).Substring(namespaceName.Length);
+
+                var path = Path.Combine(systemProfilesPath, filename);
+
+                using (var stream = assembly.GetManifestResourceStream(name))
+                {
+                    var fileInfo = new FileInfo(path);
+
+                    if (!fileInfo.Exists || fileInfo.Length != stream.Length)
+                    {
+                        Directory.CreateDirectory(systemProfilesPath);
+
+                        using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
+                        {
+                            stream.CopyTo(fileStream);
+                        }
+                    }
+                }
+            }
+
+            // Not necessary, but just to make it easy to find
+            Directory.CreateDirectory(UserProfilesPath);
+        }
+
+        public void DeleteProfile(string id)
+        {
+            var info = GetProfileInfosInternal().First(i => string.Equals(id, i.Info.Id));
+
+            if (info.Info.Type == DeviceProfileType.System)
+            {
+                throw new ArgumentException("System profiles cannot be deleted.");
+            }
+
+            File.Delete(info.Path);
+        }
+
+        public void CreateProfile(DeviceProfile profile)
+        {
+        }
+
+        public void UpdateProfile(DeviceProfile profile)
+        {
+        }
+
+        class InternalProfileInfo
+        {
+            internal DeviceProfileInfo Info { get; set; }
+            internal string Path { get; set; }
+        }
     }
 }

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

@@ -61,7 +61,6 @@
     <Compile Include="PlayTo\DeviceService.cs" />
     <Compile Include="PlayTo\DidlBuilder.cs" />
     <Compile Include="PlayTo\DlnaController.cs" />
-    <Compile Include="PlayTo\DlnaControllerFactory.cs" />
     <Compile Include="PlayTo\Extensions.cs" />
     <Compile Include="PlayTo\PlaylistItem.cs">
       <SubType>Code</SubType>
@@ -70,7 +69,8 @@
     <Compile Include="PlayTo\PlayToManager.cs" />
     <Compile Include="PlayTo\PlayToServerEntryPoint.cs" />
     <Compile Include="PlayTo\ServiceAction.cs" />
-    <Compile Include="PlayTo\SsdpHelper.cs" />
+    <Compile Include="Profiles\Foobar2000Profile.cs" />
+    <Compile Include="Ssdp\SsdpHelper.cs" />
     <Compile Include="PlayTo\SsdpHttpClient.cs" />
     <Compile Include="PlayTo\StateVariable.cs" />
     <Compile Include="PlayTo\StreamHelper.cs" />
@@ -100,7 +100,6 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Server\DlnaServerEntryPoint.cs" />
     <Compile Include="Server\Headers.cs" />
-    <Compile Include="Server\RawHeaders.cs" />
     <Compile Include="Server\SsdpHandler.cs" />
     <Compile Include="Server\UpnpDevice.cs" />
   </ItemGroup>
@@ -118,7 +117,27 @@
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <EmbeddedResource Include="Profiles\Xml\Denon AVR.xml" />
+    <EmbeddedResource Include="Profiles\Xml\foobar2000.xml" />
+    <EmbeddedResource Include="Profiles\Xml\LG Smart TV.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Linksys DMA2100.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Panasonic Viera.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Samsung Smart TV.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player 2013.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Bravia %282010%29.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Bravia %282011%29.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Bravia %282012%29.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony Bravia %282013%29.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Sony PlayStation 3.xml" />
+    <EmbeddedResource Include="Profiles\Xml\WDTV Live.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Xbox 360.xml" />
+    <EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Profiles\Xml\Default.xml" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- 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.

+ 1 - 13
MediaBrowser.Dlna/PlayTo/CurrentIdEventArgs.cs

@@ -4,18 +4,6 @@ namespace MediaBrowser.Dlna.PlayTo
 {
     public class CurrentIdEventArgs : EventArgs
     {
-        public Guid Id { get;  set; }
-
-        public CurrentIdEventArgs(string id)
-        {
-            if (string.IsNullOrWhiteSpace(id) || id == "0")
-            {
-                Id = Guid.Empty;
-            }
-            else
-            {
-                Id = new Guid(id);
-            }
-        }
+        public string Id { get;  set; }
     }
 }

+ 17 - 9
MediaBrowser.Dlna/PlayTo/Device.cs

@@ -42,6 +42,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 if (_currentId == value)
                     return;
                 _currentId = value;
+
                 NotifyCurrentIdChanged(value);
             }
         }
@@ -250,7 +251,7 @@ namespace MediaBrowser.Dlna.PlayTo
             StopTimer();
 
             await SetStop().ConfigureAwait(false);
-            CurrentId = "0";
+            CurrentId = null;
 
             var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
             if (command == null)
@@ -514,7 +515,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (String.IsNullOrEmpty(track))
             {
-                CurrentId = "0";
+                CurrentId = null;
                 return;
             }
 
@@ -607,7 +608,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 url = "/" + url;
 
             var httpClient = new SsdpHttpClient(_httpClient, _config);
-            var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url));
+            var document = await httpClient.GetDataAsync(Properties.BaseUrl + url);
 
             AvCommands = TransportCommands.Create(document);
         }
@@ -625,12 +626,12 @@ namespace MediaBrowser.Dlna.PlayTo
                 url = "/" + url;
 
             var httpClient = new SsdpHttpClient(_httpClient, _config);
-            var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url));
+            var document = await httpClient.GetDataAsync(Properties.BaseUrl + url);
 
             RendererCommands = TransportCommands.Create(document);
         }
 
-        internal TransportCommands AvCommands
+        private TransportCommands AvCommands
         {
             get;
             set;
@@ -646,7 +647,7 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
 
-            var document = await ssdpHttpClient.GetDataAsync(url).ConfigureAwait(false);
+            var document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false);
 
             var deviceProperties = new DeviceInfo();
 
@@ -681,10 +682,18 @@ namespace MediaBrowser.Dlna.PlayTo
             var presentationUrl = document.Descendants(uPnpNamespaces.ud.GetName("presentationURL")).FirstOrDefault();
             if (presentationUrl != null)
                 deviceProperties.PresentationUrl = presentationUrl.Value;
+
             var modelUrl = document.Descendants(uPnpNamespaces.ud.GetName("modelURL")).FirstOrDefault();
             if (modelUrl != null)
                 deviceProperties.ModelUrl = modelUrl.Value;
-            
+
+            var serialNumber = document.Descendants(uPnpNamespaces.ud.GetName("serialNumber")).FirstOrDefault();
+            if (serialNumber != null)
+                deviceProperties.SerialNumber = serialNumber.Value;
+
+            var modelDescription = document.Descendants(uPnpNamespaces.ud.GetName("modelDescription")).FirstOrDefault();
+            if (modelDescription != null)
+                deviceProperties.ModelDescription = modelDescription.Value;
 
             deviceProperties.BaseUrl = String.Format("http://{0}:{1}", url.Host, url.Port);
 
@@ -724,7 +733,6 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (isRenderer)
             {
-
                 var device = new Device(deviceProperties, httpClient, logger, config);
 
                 await device.GetRenderingProtocolAsync().ConfigureAwait(false);
@@ -768,7 +776,7 @@ namespace MediaBrowser.Dlna.PlayTo
         private void NotifyCurrentIdChanged(string value)
         {
             if (CurrentIdChanged != null)
-                CurrentIdChanged.Invoke(this, new CurrentIdEventArgs(value));
+                CurrentIdChanged.Invoke(this, new CurrentIdEventArgs { Id = value });
         }
 
         #endregion

+ 9 - 16
MediaBrowser.Dlna/PlayTo/DeviceInfo.cs

@@ -1,5 +1,5 @@
-using System.Collections.Generic;
-using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Controller.Dlna;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Dlna.PlayTo
 {
@@ -17,27 +17,18 @@ namespace MediaBrowser.Dlna.PlayTo
 
         public string ClientType { get; set; }
 
-        private string _displayName = string.Empty;
-        public string DisplayName
-        {
-            get
-            {
-                return string.IsNullOrEmpty(_displayName) ? Name : _displayName;
-            }
-            set
-            {
-                _displayName = value;
-            }
-        }
-
         public string ModelName { get; set; }
 
         public string ModelNumber { get; set; }
 
+        public string ModelDescription { get; set; }
+
         public string ModelUrl { get; set; }
 
         public string Manufacturer { get; set; }
 
+        public string SerialNumber { get; set; }
+
         public string ManufacturerUrl { get; set; }
 
         public string PresentationUrl { get; set; }
@@ -75,7 +66,9 @@ namespace MediaBrowser.Dlna.PlayTo
                 ModelNumber = ModelNumber,
                 FriendlyName = Name,
                 ManufacturerUrl = ManufacturerUrl,
-                ModelUrl = ModelUrl
+                ModelUrl = ModelUrl,
+                ModelDescription = ModelDescription,
+                SerialNumber = SerialNumber
             };
         }
     }

+ 44 - 41
MediaBrowser.Dlna/PlayTo/DidlBuilder.cs

@@ -9,31 +9,27 @@ namespace MediaBrowser.Dlna.PlayTo
 {
     internal class DidlBuilder
     {
-        #region Constants
-
-        internal const string CRLF = "\r\n";
-        internal const string UNKNOWN = "Unknown";
-
-        internal const string DIDL_START = @"<item id=""{0}"" parentID=""{1}"" restricted=""1"" xmlns=""urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"">" + CRLF;
-        internal const string DIDL_TITLE = @"  <dc:title xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:title>" + CRLF;
-        internal const string DIDL_ARTIST = @"<upnp:artist xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:artist>" + CRLF;
-        internal const string DIDL_ALBUM = @"<upnp:album xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:album>" + CRLF;
-        internal const string DIDL_TRACKNUM = @"<upnp:originalTrackNumber xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">0</upnp:originalTrackNumber>" + CRLF;
-        internal const string DIDL_VIDEOCLASS = @"  <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.videoItem</upnp:class>" + CRLF;
-        internal const string DIDL_AUDIOCLASS = @"  <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.audioItem.musicTrack</upnp:class>" + CRLF;
-        internal const string DIDL_IMAGE = @"  <upnp:albumArtURI dlna:profileID=""JPEG_TN"" xmlns:dlna=""urn:schemas-dlna-org:metadata-1-0/"" xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:albumArtURI>" + CRLF +
-                                                @"  <upnp:icon xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:icon>" + CRLF;
-        internal const string DIDL_RELEASEDATE = @"  <dc:date xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:date>" + CRLF;
-        internal const string DIDL_GENRE = @"  <upnp:genre xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:genre>" + CRLF;
-        internal const string DESCRIPTION = @"  <dc:description xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:description>" + CRLF;
-        internal const string DIDL_VIDEO_RES = @"  <res bitrate=""{0}"" duration=""{1}"" protocolInfo=""http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" resolution=""{2}x{3}"" size=""0"">{4}</res>" + CRLF;
-        internal const string DIDL_AUDIO_RES = @"  <res bitrate=""{0}"" duration=""{1}"" nrAudioChannels=""2"" protocolInfo=""http-get:*:audio/mp3:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" sampleFrequency=""{2}"" size=""0"">{3}</res>" + CRLF;
-        internal const string DIDL_IMAGE_RES = @"  <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""212x320"">{0}</res>" + CRLF;
-        internal const string DIDL_ALBUMIMAGE_RES = @"  <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""320x320"">{0}</res>" + CRLF;
-        internal const string DIDL_RATING = @"  <upnp:rating xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:rating>" + CRLF;
-        internal const string DIDL_END = "</item>";
-
-        #endregion
+        const string CRLF = "\r\n";
+        const string UNKNOWN = "Unknown";
+
+        const string DIDL_START = @"<item id=""{0}"" parentID=""{1}"" restricted=""1"" xmlns=""urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"">" + CRLF;
+        const string DIDL_TITLE = @"  <dc:title xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:title>" + CRLF;
+        const string DIDL_ARTIST = @"<upnp:artist xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:artist>" + CRLF;
+        const string DIDL_ALBUM = @"<upnp:album xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:album>" + CRLF;
+        const string DIDL_TRACKNUM = @"<upnp:originalTrackNumber xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:originalTrackNumber>" + CRLF;
+        const string DIDL_VIDEOCLASS = @"  <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.videoItem</upnp:class>" + CRLF;
+        const string DIDL_AUDIOCLASS = @"  <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.audioItem.musicTrack</upnp:class>" + CRLF;
+        const string DIDL_IMAGE = @"  <upnp:albumArtURI dlna:profileID=""JPEG_TN"" xmlns:dlna=""urn:schemas-dlna-org:metadata-1-0/"" xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:albumArtURI>" + CRLF +
+                                               @"  <upnp:icon xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:icon>" + CRLF;
+        const string DIDL_RELEASEDATE = @"  <dc:date xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:date>" + CRLF;
+        const string DIDL_GENRE = @"  <upnp:genre xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:genre>" + CRLF;
+        const string DESCRIPTION = @"  <dc:description xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:description>" + CRLF;
+        const string DIDL_VIDEO_RES = @"  <res bitrate=""{0}"" duration=""{1}"" protocolInfo=""http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" resolution=""{2}x{3}"" size=""0"">{4}</res>" + CRLF;
+        const string DIDL_AUDIO_RES = @"  <res bitrate=""{0}"" duration=""{1}"" nrAudioChannels=""2"" protocolInfo=""http-get:*:audio/mp3:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" sampleFrequency=""{2}"" size=""0"">{3}</res>" + CRLF;
+        const string DIDL_IMAGE_RES = @"  <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""212x320"">{0}</res>" + CRLF;
+        const string DIDL_ALBUMIMAGE_RES = @"  <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""320x320"">{0}</res>" + CRLF;
+        const string DIDL_RATING = @"  <upnp:rating xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:rating>" + CRLF;
+        const string DIDL_END = "</item>";
 
         /// <summary>
         /// Builds a Didl MetaData object for the specified dto.
@@ -44,7 +40,7 @@ namespace MediaBrowser.Dlna.PlayTo
         /// <param name="streamUrl">The stream URL.</param>
         /// <param name="streams">The streams.</param>
         /// <returns>System.String.</returns>
-        internal static string Build(BaseItem dto, string userId, string serverAddress, string streamUrl, IEnumerable<MediaStream> streams)
+        public static string Build(BaseItem dto, string userId, string serverAddress, string streamUrl, IEnumerable<MediaStream> streams, bool includeImageRes)
         {
             string response = string.Format(DIDL_START, dto.Id, userId);
             response += string.Format(DIDL_TITLE, dto.Name.Replace("&", "and"));
@@ -53,7 +49,12 @@ namespace MediaBrowser.Dlna.PlayTo
             else
                 response += DIDL_AUDIOCLASS;
 
-            response += string.Format(DIDL_IMAGE, GetImageUrl(dto, serverAddress));
+            var imageUrl = GetImageUrl(dto, serverAddress);
+
+            if (!string.IsNullOrWhiteSpace(imageUrl))
+            {
+                response += string.Format(DIDL_IMAGE, imageUrl);
+            }
             response += string.Format(DIDL_RELEASEDATE, GetDateString(dto.PremiereDate));
 
             //TODO Add genres to didl;
@@ -63,7 +64,11 @@ namespace MediaBrowser.Dlna.PlayTo
             {
                 response += string.Format(DESCRIPTION, UNKNOWN);
                 response += GetVideoDIDL(dto, streamUrl, streams);
-                response += string.Format(DIDL_IMAGE_RES, GetImageUrl(dto, serverAddress));
+
+                if (includeImageRes && !string.IsNullOrWhiteSpace(imageUrl))
+                {
+                    response += string.Format(DIDL_IMAGE_RES, imageUrl);
+                }
             }
             else
             {
@@ -74,25 +79,25 @@ namespace MediaBrowser.Dlna.PlayTo
                     response += string.Format(DIDL_ARTIST, audio.Artists.FirstOrDefault() ?? UNKNOWN);
                     response += string.Format(DIDL_ALBUM, audio.Album);
 
-                    // TODO: Bad format string?
                     response += string.Format(DIDL_TRACKNUM, audio.IndexNumber ?? 0);
                 }
 
                 response += GetAudioDIDL(dto, streamUrl, streams);
-                response += string.Format(DIDL_ALBUMIMAGE_RES, GetImageUrl(dto, serverAddress));
+
+                if (includeImageRes && !string.IsNullOrWhiteSpace(imageUrl))
+                {
+                    response += string.Format(DIDL_ALBUMIMAGE_RES, imageUrl);
+                }
             }
 
             response += DIDL_END;
 
             return response;
-
         }
 
-        #region Private methods
-
         private static string GetVideoDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
         {
-            var videostream = streams.Where(stream => stream.Type == Model.Entities.MediaStreamType.Video).OrderBy(s => s.IsDefault).FirstOrDefault();
+            var videostream = streams.Where(stream => stream.Type == MediaStreamType.Video).OrderBy(s => s.IsDefault ? 0 : 1).FirstOrDefault();
 
             if (videostream == null)
             {
@@ -105,7 +110,7 @@ namespace MediaBrowser.Dlna.PlayTo
 
         private static string GetAudioDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
         {
-            var audiostream = streams.Where(stream => stream.Type == MediaStreamType.Audio).OrderBy(s => s.IsDefault).FirstOrDefault();
+            var audiostream = streams.Where(stream => stream.Type == MediaStreamType.Audio).OrderBy(s => s.IsDefault ? 0 : 1).FirstOrDefault();
 
             if (audiostream == null)
             {
@@ -118,14 +123,14 @@ namespace MediaBrowser.Dlna.PlayTo
 
         private static string GetImageUrl(BaseItem dto, string serverAddress)
         {
-            var imageType = ImageType.Primary;
+            const ImageType imageType = ImageType.Primary;
 
-            if (!dto.HasImage(ImageType.Primary))
+            if (!dto.HasImage(imageType))
             {
-                dto = dto.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+                dto = dto.Parents.FirstOrDefault(i => i.HasImage(imageType));
             }
 
-            return string.Format("{0}/Items/{1}/Images/{2}", serverAddress, dto.Id, imageType);
+            return dto == null ? null : string.Format("{0}/Items/{1}/Images/{2}", serverAddress, dto.Id, imageType);
         }
 
         private static string GetDurationString(BaseItem dto)
@@ -148,7 +153,5 @@ namespace MediaBrowser.Dlna.PlayTo
         {
             return string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
         }
-
-        #endregion
     }
 }

+ 45 - 20
MediaBrowser.Dlna/PlayTo/DlnaController.cs

@@ -20,7 +20,7 @@ namespace MediaBrowser.Dlna.PlayTo
     public class PlayToController : ISessionController, IDisposable
     {
         private Device _device;
-        private BaseItem _currentItem = null;
+        private BaseItem _currentItem;
         private readonly SessionInfo _session;
         private readonly ISessionManager _sessionManager;
         private readonly IItemRepository _itemRepository;
@@ -30,7 +30,7 @@ namespace MediaBrowser.Dlna.PlayTo
         private readonly IDlnaManager _dlnaManager;
         private readonly IUserManager _userManager;
         private readonly IServerApplicationHost _appHost;
-        private bool _playbackStarted = false;
+        private bool _playbackStarted;
 
         private const int UpdateTimerIntervalMs = 1000;
 
@@ -103,22 +103,27 @@ namespace MediaBrowser.Dlna.PlayTo
 
         async void Device_CurrentIdChanged(object sender, CurrentIdEventArgs e)
         {
-            if (e.Id != Guid.Empty)
+            if (!string.IsNullOrWhiteSpace(e.Id))
             {
-                if (_currentItem != null && _currentItem.Id == e.Id)
+                Guid guid;
+
+                if (Guid.TryParse(e.Id, out guid))
                 {
-                    return;
-                }
+                    if (_currentItem != null && _currentItem.Id == guid)
+                    {
+                        return;
+                    }
 
-                var item = _libraryManager.GetItemById(e.Id);
+                    var item = _libraryManager.GetItemById(guid);
 
-                if (item != null)
-                {
-                    _logger.Debug("{0} - CurrentId {1}", _session.DeviceName, item.Id);
-                    _currentItem = item;
-                    _playbackStarted = false;
+                    if (item != null)
+                    {
+                        _logger.Debug("{0} - CurrentId {1}", _session.DeviceName, item.Id);
+                        _currentItem = item;
+                        _playbackStarted = false;
 
-                    await ReportProgress().ConfigureAwait(false);
+                        await ReportProgress().ConfigureAwait(false);
+                    }
                 }
             }
         }
@@ -140,8 +145,15 @@ namespace MediaBrowser.Dlna.PlayTo
             {
                 _updateTimer.Change(Timeout.Infinite, Timeout.Infinite);
 
-                //Session is inactive, mark it for Disposal and don't start the elapsed timer.
-                await _sessionManager.ReportSessionEnded(_session.Id);
+                try
+                {
+                    // Session is inactive, mark it for Disposal and don't start the elapsed timer.
+                    await _sessionManager.ReportSessionEnded(_session.Id);
+                }
+                catch (Exception ex)
+                {
+                    _logger.ErrorException("Error in ReportSessionEnded", ex);
+                }
             }
         }
 
@@ -156,7 +168,15 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (!_playbackStarted)
             {
-                await _sessionManager.OnPlaybackStart(new PlaybackInfo { Item = _currentItem, SessionId = _session.Id, CanSeek = true, QueueableMediaTypes = new List<string> { "Audio", "Video" } }).ConfigureAwait(false);
+                await _sessionManager.OnPlaybackStart(new PlaybackInfo
+                {
+                    Item = _currentItem, 
+                    SessionId = _session.Id, 
+                    CanSeek = true,
+                    QueueableMediaTypes = new List<string> { _currentItem.MediaType }
+
+                }).ConfigureAwait(false);
+
                 _playbackStarted = true;
             }
 
@@ -399,11 +419,12 @@ namespace MediaBrowser.Dlna.PlayTo
 
             var deviceInfo = _device.Properties;
 
-            var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification());
+            var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ??
+                _dlnaManager.GetDefaultProfile();
 
             var playlistItem = GetPlaylistItem(item, streams, profile);
             playlistItem.StartPositionTicks = startPostionTicks;
-            playlistItem.DeviceProfileName = profile.Name;
+            playlistItem.DeviceProfileId = profile.Id;
 
             if (playlistItem.MediaType == DlnaProfileType.Audio)
             {
@@ -414,8 +435,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 playlistItem.StreamUrl = StreamHelper.GetVideoUrl(_device.Properties, playlistItem, streams, serverAddress);
             }
 
-            var didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams);
-            playlistItem.Didl = didl;
+            playlistItem.Didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams, profile.EnableAlbumArtInDidl);
 
             return playlistItem;
         }
@@ -599,5 +619,10 @@ namespace MediaBrowser.Dlna.PlayTo
                 _logger.Log(LogSeverity.Debug, "Controller disposed");
             }
         }
+
+        public Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 0 - 31
MediaBrowser.Dlna/PlayTo/DlnaControllerFactory.cs

@@ -1,31 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Logging;
-
-namespace MediaBrowser.Dlna.PlayTo
-{
-    public class PlayToControllerFactory : ISessionControllerFactory
-    {
-        private readonly ISessionManager _sessionManager;
-        private readonly IItemRepository _itemRepository;
-        private readonly ILibraryManager _libraryManager;
-        private readonly ILogger _logger;
-        private readonly INetworkManager _networkManager;
-
-        public PlayToControllerFactory(ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogManager logManager, INetworkManager networkManager)
-        {
-            _itemRepository = itemRepository;
-            _sessionManager = sessionManager;
-            _libraryManager = libraryManager;
-            _networkManager = networkManager;
-            _logger = logManager.GetLogger("PlayTo");
-        }
-
-        public ISessionController GetSessionController(SessionInfo session)
-        {
-            return null;
-        }
-    }
-}

+ 25 - 35
MediaBrowser.Dlna/PlayTo/PlayToManager.cs

@@ -5,16 +5,17 @@ using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Session;
+using MediaBrowser.Dlna.Ssdp;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Session;
 using System;
 using System.Collections.Concurrent;
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -126,10 +127,9 @@ namespace MediaBrowser.Dlna.PlayTo
 
                         if (receivedBytes > 0)
                         {
-                            var rawData = Encoding.UTF8.GetString(receiveBuffer, 0, receivedBytes);
-                            var uri = SsdpHelper.ParseSsdpResponse(rawData);
+                            var headers = SsdpHelper.ParseSsdpResponse(receiveBuffer);
 
-                            TryCreateController(uri);
+                            TryCreateController(headers);
                         }
                     }
 
@@ -146,13 +146,20 @@ namespace MediaBrowser.Dlna.PlayTo
             }, _tokenSource.Token, TaskCreationOptions.LongRunning);
         }
 
-        private void TryCreateController(Uri uri)
+        private void TryCreateController(IDictionary<string,string> headers)
         {
+            string location;
+
+            if (!headers.TryGetValue("Location", out location))
+            {
+                return;
+            }
+
             Task.Run(async () =>
             {
                 try
                 {
-                    await CreateController(uri).ConfigureAwait(false);
+                    await CreateController(new Uri(location)).ConfigureAwait(false);
                 }
                 catch (OperationCanceledException)
                 {
@@ -221,46 +228,29 @@ namespace MediaBrowser.Dlna.PlayTo
 
             if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive))
             {
-                GetProfileSettings(device.Properties);
-
-                var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, device.Properties.Name, device.Properties.UUID, device.Properties.DisplayName, uri.OriginalString, null)
+                var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
                     .ConfigureAwait(false);
 
-                _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
-                {
-                    PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo },
-                    SupportsFullscreenToggle = false
-                });
-
                 var controller = sessionInfo.SessionController as PlayToController;
 
                 if (controller == null)
                 {
                     sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager, _dlnaManager, _userManager, _appHost);
-                }
 
-                controller.Init(device);
+                    controller.Init(device);
 
-                _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
-            }
-        }
+                    var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
+                                  _dlnaManager.GetDefaultProfile();
 
-        /// <summary>
-        /// Gets the profile settings.
-        /// </summary>
-        /// <param name="deviceProperties">The device properties.</param>
-        /// <returns>The TranscodeSettings for the device</returns>
-        private void GetProfileSettings(DeviceInfo deviceProperties)
-        {
-            var profile = _dlnaManager.GetProfile(deviceProperties.ToDeviceIdentification());
+                    _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
+                    {
+                        PlayableMediaTypes = profile.GetSupportedMediaTypes().ToArray(),
 
-            if (!string.IsNullOrWhiteSpace(profile.Name))
-            {
-                deviceProperties.DisplayName = profile.Name;
-            }
-            if (!string.IsNullOrWhiteSpace(profile.ClientType))
-            {
-                deviceProperties.ClientType = profile.ClientType;
+                        SupportsFullscreenToggle = false
+                    });
+
+                    _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
+                }
             }
         }
 

+ 2 - 2
MediaBrowser.Dlna/PlayTo/PlaylistItem.cs

@@ -33,8 +33,6 @@ namespace MediaBrowser.Dlna.PlayTo
 
         public int? SubtitleStreamIndex { get; set; }
 
-        public string DeviceProfileName { get; set; }
-
         public int? MaxAudioChannels { get; set; }
 
         public int? AudioBitrate { get; set; }
@@ -48,6 +46,8 @@ namespace MediaBrowser.Dlna.PlayTo
 
         public int? MaxFramerate { get; set; }
 
+        public string DeviceProfileId { get; set; }
+
         public PlaylistItem()
         {
             TranscodingSettings = new List<TranscodingSetting>();

+ 15 - 22
MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs

@@ -32,7 +32,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 var audioCodec = audioStream == null ? null : audioStream.Codec;
 
                 // Make sure audio codec profiles are satisfied
-                if (!string.IsNullOrEmpty(audioCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.AudioCodec && i.ContainsCodec(audioCodec))
+                if (!string.IsNullOrEmpty(audioCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
                     .All(i => AreConditionsSatisfied(i.Conditions, item.Path, null, audioStream)))
                 {
                     playlistItem.Transcode = false;
@@ -53,7 +53,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 playlistItem.AudioCodec = transcodingProfile.AudioCodec;
 
                 var audioTranscodingConditions = profile.CodecProfiles
-                    .Where(i => i.Type == CodecType.AudioCodec && i.ContainsCodec(transcodingProfile.AudioCodec))
+                    .Where(i => i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
                     .Take(1)
                     .SelectMany(i => i.Conditions);
 
@@ -114,13 +114,13 @@ namespace MediaBrowser.Dlna.PlayTo
                 var videoCodec = videoStream == null ? null : videoStream.Codec;
 
                 // Make sure video codec profiles are satisfied
-                if (!string.IsNullOrEmpty(videoCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.VideoCodec && i.ContainsCodec(videoCodec))
+                if (!string.IsNullOrEmpty(videoCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
                     .All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
                 {
                     var audioCodec = audioStream == null ? null : audioStream.Codec;
 
                     // Make sure audio codec profiles are satisfied
-                    if (string.IsNullOrEmpty(audioCodec) || profile.CodecProfiles.Where(i => i.Type == CodecType.VideoAudioCodec && i.ContainsCodec(audioCodec))
+                    if (string.IsNullOrEmpty(audioCodec) || profile.CodecProfiles.Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
                         .All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
                     {
                         playlistItem.Transcode = false;
@@ -143,14 +143,14 @@ namespace MediaBrowser.Dlna.PlayTo
                 playlistItem.VideoCodec = transcodingProfile.VideoCodec;
 
                 var videoTranscodingConditions = profile.CodecProfiles
-                    .Where(i => i.Type == CodecType.VideoCodec && i.ContainsCodec(transcodingProfile.VideoCodec))
+                    .Where(i => i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
                     .Take(1)
                     .SelectMany(i => i.Conditions);
 
                 ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
 
                 var audioTranscodingConditions = profile.CodecProfiles
-                    .Where(i => i.Type == CodecType.VideoAudioCodec && i.ContainsCodec(transcodingProfile.AudioCodec))
+                    .Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
                     .Take(1)
                     .SelectMany(i => i.Conditions);
 
@@ -162,7 +162,8 @@ namespace MediaBrowser.Dlna.PlayTo
 
         private void ApplyTranscodingConditions(PlaylistItem item, IEnumerable<ProfileCondition> conditions)
         {
-            foreach (var condition in conditions.Where(i => !string.IsNullOrEmpty(i.Value)))
+            foreach (var condition in conditions
+                .Where(i => !string.IsNullOrEmpty(i.Value)))
             {
                 var value = condition.Value;
 
@@ -170,7 +171,7 @@ namespace MediaBrowser.Dlna.PlayTo
                 {
                     case ProfileConditionValue.AudioBitrate:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.AudioBitrate = num;
@@ -179,7 +180,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     }
                     case ProfileConditionValue.AudioChannels:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.MaxAudioChannels = num;
@@ -190,16 +191,14 @@ namespace MediaBrowser.Dlna.PlayTo
                     case ProfileConditionValue.AudioProfile:
                     case ProfileConditionValue.Has64BitOffsets:
                     case ProfileConditionValue.VideoBitDepth:
-                    case ProfileConditionValue.VideoPacketLength:
                     case ProfileConditionValue.VideoProfile:
-                    case ProfileConditionValue.VideoTimestamp:
                     {
                         // Not supported yet
                         break;
                     }
                     case ProfileConditionValue.Height:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.MaxHeight = num;
@@ -208,7 +207,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     }
                     case ProfileConditionValue.VideoBitrate:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.VideoBitrate = num;
@@ -217,7 +216,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     }
                     case ProfileConditionValue.VideoFramerate:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.MaxFramerate = num;
@@ -226,7 +225,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     }
                     case ProfileConditionValue.VideoLevel:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.VideoLevel = num;
@@ -235,7 +234,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     }
                     case ProfileConditionValue.Width:
                     {
-                        var num = 0;
+                        int num;
                         if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
                         {
                             item.MaxWidth = num;
@@ -460,12 +459,6 @@ namespace MediaBrowser.Dlna.PlayTo
                     return videoStream == null ? null : videoStream.Width;
                 case ProfileConditionValue.VideoLevel:
                     return videoStream == null ? null : ConvertToLong(videoStream.Level);
-                case ProfileConditionValue.VideoPacketLength:
-                    // TODO: Determine how to get this
-                    return null;
-                case ProfileConditionValue.VideoTimestamp:
-                    // TODO: Determine how to get this
-                    return null;
                 default:
                     throw new InvalidOperationException("Unexpected Property");
             }

+ 25 - 15
MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs

@@ -2,7 +2,6 @@
 using MediaBrowser.Controller.Configuration;
 using System;
 using System.IO;
-using System.Net;
 using System.Text;
 using System.Threading.Tasks;
 using System.Xml.Linq;
@@ -14,8 +13,6 @@ namespace MediaBrowser.Dlna.PlayTo
         private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
         private const string FriendlyName = "MediaBrowser";
 
-        private static readonly CookieContainer Container = new CookieContainer();
-
         private readonly IHttpClient _httpClient;
         private readonly IServerConfigurationManager _config;
 
@@ -25,13 +22,17 @@ namespace MediaBrowser.Dlna.PlayTo
             _config = config;
         }
 
-        public async Task<XDocument> SendCommandAsync(string baseUrl, DeviceService service, string command, string postData, string header = null)
+        public async Task<XDocument> SendCommandAsync(string baseUrl, 
+            DeviceService service, 
+            string command, 
+            string postData, 
+            string header = null)
         {
             var serviceUrl = service.ControlUrl;
             if (!serviceUrl.StartsWith("/"))
                 serviceUrl = "/" + serviceUrl;
 
-            var response = await PostSoapDataAsync(new Uri(baseUrl + serviceUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header)
+            var response = await PostSoapDataAsync(baseUrl + serviceUrl, "\"" + service.ServiceType + "#" + command + "\"", postData, header)
                 .ConfigureAwait(false);
 
             using (var stream = response.Content)
@@ -43,11 +44,16 @@ namespace MediaBrowser.Dlna.PlayTo
             }
         }
 
-        public async Task SubscribeAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 3600)
+        public async Task SubscribeAsync(string url, 
+            string ip, 
+            int port, 
+            string localIp, 
+            int eventport, 
+            int timeOut = 3600)
         {
             var options = new HttpRequestOptions
             {
-                Url = url.ToString(),
+                Url = url,
                 UserAgent = USERAGENT,
                 LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
             };
@@ -56,14 +62,17 @@ namespace MediaBrowser.Dlna.PlayTo
             options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
             options.RequestHeaders["NT"] = "upnp:event";
             options.RequestHeaders["TIMEOUT"] = "Second - " + timeOut;
-            //request.CookieContainer = Container;
 
             using (await _httpClient.Get(options).ConfigureAwait(false))
             {
             }
         }
 
-        public async Task RespondAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 20000)
+        public async Task RespondAsync(Uri url, 
+            string ip, 
+            int port, 
+            string localIp, 
+            int eventport)
         {
             var options = new HttpRequestOptions
             {
@@ -75,24 +84,22 @@ namespace MediaBrowser.Dlna.PlayTo
             options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
             options.RequestHeaders["NT"] = "upnp:event";
             options.RequestHeaders["TIMEOUT"] = "Second - 3600";
-            //request.CookieContainer = Container;
 
             using (await _httpClient.Get(options).ConfigureAwait(false))
             {
             }
         }
 
-        public async Task<XDocument> GetDataAsync(Uri url)
+        public async Task<XDocument> GetDataAsync(string url)
         {
             var options = new HttpRequestOptions
             {
-                Url = url.ToString(),
+                Url = url,
                 UserAgent = USERAGENT,
                 LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
             };
 
             options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
-            //request.CookieContainer = Container;
 
             using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
             {
@@ -103,14 +110,17 @@ namespace MediaBrowser.Dlna.PlayTo
             }
         }
 
-        private Task<HttpResponseInfo> PostSoapDataAsync(Uri url, string soapAction, string postData, string header = null, int timeOut = 20000)
+        private Task<HttpResponseInfo> PostSoapDataAsync(string url, 
+            string soapAction, 
+            string postData, 
+            string header = null)
         {
             if (!soapAction.StartsWith("\""))
                 soapAction = "\"" + soapAction + "\"";
 
             var options = new HttpRequestOptions
             {
-                Url = url.ToString(),
+                Url = url,
                 UserAgent = USERAGENT,
                 LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
             };

+ 2 - 9
MediaBrowser.Dlna/PlayTo/StreamHelper.cs

@@ -1,8 +1,6 @@
-using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Globalization;
-using System.Linq;
 
 namespace MediaBrowser.Dlna.PlayTo
 {
@@ -43,15 +41,11 @@ namespace MediaBrowser.Dlna.PlayTo
         /// </summary>
         private static string BuildDlnaUrl(DeviceInfo deviceProperties, PlaylistItem item)
         {
-            var profile = item.TranscodingSettings.Where(i => i.Name == TranscodingSettingType.VideoProfile)
-                .Select(i => i.Value)
-                .FirstOrDefault();
-
             var usCulture = new CultureInfo("en-US");
             
             var list = new List<string>
             {
-                item.DeviceProfileName ?? string.Empty,
+                item.DeviceProfileId ?? string.Empty,
                 deviceProperties.UUID ?? string.Empty,
                 item.MediaSourceId ?? string.Empty,
                 (!item.Transcode).ToString().ToLower(),
@@ -66,7 +60,6 @@ namespace MediaBrowser.Dlna.PlayTo
                 item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(usCulture) : string.Empty,
                 item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(usCulture) : string.Empty,
                 item.StartPositionTicks.ToString(usCulture),
-                profile ?? string.Empty,
                 item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(usCulture) : string.Empty
             };
 

+ 5 - 19
MediaBrowser.Dlna/Profiles/DefaultProfile.cs

@@ -1,14 +1,18 @@
 using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class DefaultProfile : DeviceProfile
     {
         public DefaultProfile()
         {
+            Name = "Generic Device";
+
             ProtocolInfo = "DLNA";
 
-            ClientType = "DLNA";
+            FriendlyName = "Media Browser";
             Manufacturer = "Media Browser";
             ModelDescription = "Media Browser";
             ModelName = "Media Browser";
@@ -53,24 +57,6 @@ namespace MediaBrowser.Dlna.Profiles
                     Type = DlnaProfileType.Video
                 }
             };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.VideoCodec,
-                    Conditions = new []
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "3",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
         }
     }
 }

+ 3 - 1
MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class DenonAvrProfile : DefaultProfile
     {
         public DenonAvrProfile()

+ 31 - 0
MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs

@@ -0,0 +1,31 @@
+using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+    [XmlRoot("Profile")]
+    public class Foobar2000Profile : DefaultProfile
+    {
+        public Foobar2000Profile()
+        {
+            Name = "foobar2000";
+
+            SupportedMediaTypes = "Audio";
+            
+            Identification = new DeviceIdentification
+            {
+                FriendlyName = @"foobar",
+
+                Headers = new[]
+               {
+                   new HttpHeaderInfo
+                   {
+                       Name = "User-Agent",
+                       Value = "foobar",
+                       Match = HeaderMatchType.Substring
+                   }
+               }
+            };
+        }
+    }
+}

+ 6 - 4
MediaBrowser.Dlna/Profiles/LgTvProfile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class LgTvProfile : DefaultProfile
     {
         public LgTvProfile()
@@ -111,7 +113,7 @@ namespace MediaBrowser.Dlna.Profiles
            {
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "mpeg4",
 
                    Conditions = new[]
@@ -139,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "h264",
 
                    Conditions = new[]
@@ -173,7 +175,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoAudioCodec,
+                   Type = CodecType.VideoAudio,
                    Codec = "ac3,aac,mp3",
 
                    Conditions = new[]

+ 3 - 1
MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class LinksysDMA2100Profile : DefaultProfile
     {
         public LinksysDMA2100Profile()

+ 20 - 18
MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs

@@ -1,19 +1,21 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
-   public class PanasonicVieraProfile : DefaultProfile
+    [XmlRoot("Profile")]
+    public class PanasonicVieraProfile : DefaultProfile
     {
-       public PanasonicVieraProfile()
-       {
-           Name = "Panasonic Viera";
+        public PanasonicVieraProfile()
+        {
+            Name = "Panasonic Viera";
 
-           Identification = new DeviceIdentification
-           {
-               FriendlyName = @"VIERA",
-               Manufacturer = "Panasonic",
+            Identification = new DeviceIdentification
+            {
+                FriendlyName = @"VIERA",
+                Manufacturer = "Panasonic",
 
-               Headers = new[]
+                Headers = new[]
                {
                    new HttpHeaderInfo
                    {
@@ -22,11 +24,11 @@ namespace MediaBrowser.Dlna.Profiles
                        Match = HeaderMatchType.Substring
                    }
                }
-           };
+            };
 
-           TimelineOffsetSeconds = 10;
+            TimelineOffsetSeconds = 10;
 
-           TranscodingProfiles = new[]
+            TranscodingProfiles = new[]
            {
                new TranscodingProfile
                {
@@ -48,7 +50,7 @@ namespace MediaBrowser.Dlna.Profiles
                }
            };
 
-           DirectPlayProfiles = new[]
+            DirectPlayProfiles = new[]
            {
                new DirectPlayProfile
                {
@@ -127,7 +129,7 @@ namespace MediaBrowser.Dlna.Profiles
                }
            };
 
-           ContainerProfiles = new[]
+            ContainerProfiles = new[]
             {
                 new ContainerProfile
                 {
@@ -151,11 +153,11 @@ namespace MediaBrowser.Dlna.Profiles
                 }
             };
 
-           CodecProfiles = new[]
+            CodecProfiles = new[]
            {
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
 
                    Conditions = new[]
                    {
@@ -181,6 +183,6 @@ namespace MediaBrowser.Dlna.Profiles
                    }
                }
            };
-       }
+        }
     }
 }

+ 16 - 7
MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs

@@ -1,14 +1,16 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SamsungSmartTvProfile : DefaultProfile
     {
         public SamsungSmartTvProfile()
         {
             Name = "Samsung Smart TV";
 
-            SupportsAlbumArtInDidl = true;
+            EnableAlbumArtInDidl = true;
 
             Identification = new DeviceIdentification
             {
@@ -143,7 +145,7 @@ namespace MediaBrowser.Dlna.Profiles
            {
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "mpeg2video",
 
                    Conditions = new[]
@@ -177,7 +179,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "mpeg4",
 
                    Conditions = new[]
@@ -211,7 +213,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "h264",
 
                    Conditions = new[]
@@ -251,7 +253,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoCodec,
+                   Type = CodecType.Video,
                    Codec = "wmv2,wmv3,vc1",
 
                    Conditions = new[]
@@ -285,7 +287,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                new CodecProfile
                {
-                   Type = CodecType.VideoAudioCodec,
+                   Type = CodecType.VideoAudio,
                    Codec = "ac3,wmav2,dca,aac,mp3",
 
                    Conditions = new[]
@@ -302,6 +304,13 @@ namespace MediaBrowser.Dlna.Profiles
 
             MediaProfiles = new[]
             {
+                new MediaProfile
+                {
+                    Container = "avi",
+                    MimeType = "video/x-msvideo",
+                    Type = DlnaProfileType.Video
+                },
+
                 new MediaProfile
                 {
                     Container = "mkv",

+ 7 - 3
MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs

@@ -1,11 +1,15 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBlurayPlayer2013Profile : DefaultProfile
     {
         public SonyBlurayPlayer2013Profile()
         {
+            Name = "Sony Blu-ray Player 2013";
+
             Identification = new DeviceIdentification
             {
                 FriendlyName = @"Blu-ray Disc Player",
@@ -109,7 +113,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
                     Conditions = new []
                     {
@@ -137,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
                     Conditions = new []
                     {

+ 8 - 4
MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs

@@ -1,11 +1,15 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBlurayPlayerProfile : DefaultProfile
     {
         public SonyBlurayPlayerProfile()
         {
+            Name = "Sony Blu-ray Player";
+
             Identification = new DeviceIdentification
             {
                 FriendlyName = @"Blu-ray Disc Player",
@@ -105,7 +109,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
                     Conditions = new []
                     {
@@ -147,7 +151,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
                     Conditions = new []
                     {
@@ -163,7 +167,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
                     Conditions = new []
                     {

+ 10 - 19
MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBravia2010Profile : DefaultProfile
     {
         public SonyBravia2010Profile()
@@ -96,13 +98,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -112,12 +108,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -177,7 +168,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Conditions = new []
                     {
                         new ProfileCondition
@@ -197,7 +188,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
                     Conditions = new []
                     {
@@ -224,7 +215,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "mpeg2video",
                     Conditions = new []
                     {
@@ -245,7 +236,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
 
                     Conditions = new []
@@ -261,7 +252,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
 
                     Conditions = new []

+ 10 - 19
MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBravia2011Profile : DefaultProfile
     {
         public SonyBravia2011Profile()
@@ -138,13 +140,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -154,12 +150,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -195,7 +186,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Conditions = new []
                     {
                         new ProfileCondition
@@ -215,7 +206,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
                     Conditions = new []
                     {
@@ -242,7 +233,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "mpeg2video",
                     Conditions = new []
                     {
@@ -263,7 +254,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
 
                     Conditions = new []
@@ -279,7 +270,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
 
                     Conditions = new[]

+ 7 - 16
MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBravia2012Profile : DefaultProfile
     {
         public SonyBravia2012Profile()
@@ -126,13 +128,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -142,12 +138,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -207,7 +198,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Conditions = new[]
                     {
                         new ProfileCondition
@@ -227,7 +218,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
 
                     Conditions = new[]

+ 6 - 15
MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyBravia2013Profile : DefaultProfile
     {
         public SonyBravia2013Profile()
@@ -182,13 +184,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -198,12 +194,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -240,7 +231,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
 
                     Conditions = new []
                     {

+ 8 - 6
MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class SonyPs3Profile : DefaultProfile
     {
         public SonyPs3Profile()
@@ -83,7 +85,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
 
                     Conditions = new []
@@ -126,7 +128,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3",
 
                     Conditions = new []
@@ -151,7 +153,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "wmapro",
 
                     Conditions = new []
@@ -167,7 +169,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
 
                     Conditions = new []
@@ -184,7 +186,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
 
                     Conditions = new []

+ 4 - 2
MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs

@@ -1,7 +1,9 @@
 using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class WdtvLiveProfile : DefaultProfile
     {
         public WdtvLiveProfile()
@@ -193,7 +195,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
 
                     Conditions = new []
@@ -221,7 +223,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
 
                     Conditions = new []

+ 8 - 20
MediaBrowser.Dlna/Profiles/Xbox360Profile.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class Xbox360Profile : DefaultProfile
     {
         public Xbox360Profile()
@@ -163,7 +165,7 @@ namespace MediaBrowser.Dlna.Profiles
             {
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "mpeg4",
                     Conditions = new []
                     {
@@ -198,7 +200,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "h264",
                     Conditions = new []
                     {
@@ -227,20 +229,13 @@ namespace MediaBrowser.Dlna.Profiles
                             Property = ProfileConditionValue.VideoBitrate,
                             Value = "10240000",
                             IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "3",
-                            IsRequired = false
                         }
                     }
                 },
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoCodec,
+                    Type = CodecType.Video,
                     Codec = "wmv2,wmv3,vc1",
                     Conditions = new []
                     {
@@ -269,20 +264,13 @@ namespace MediaBrowser.Dlna.Profiles
                             Property = ProfileConditionValue.VideoBitrate,
                             Value = "15360000",
                             IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "3",
-                            IsRequired = false
                         }
                     }
                 },
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "ac3,wmav2,wmapro",
                     Conditions = new []
                     {
@@ -298,7 +286,7 @@ namespace MediaBrowser.Dlna.Profiles
 
                 new CodecProfile
                 {
-                    Type = CodecType.VideoAudioCodec,
+                    Type = CodecType.VideoAudio,
                     Codec = "aac",
                     Conditions = new []
                     {

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

@@ -1,7 +1,9 @@
-using MediaBrowser.Controller.Dlna;
+using System.Xml.Serialization;
+using MediaBrowser.Controller.Dlna;
 
 namespace MediaBrowser.Dlna.Profiles
 {
+    [XmlRoot("Profile")]
     public class XboxOneProfile : DefaultProfile
     {
         public XboxOneProfile()

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

@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Generic Device</Name>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,wma" type="Audio" />
+    <DirectPlayProfile container="avi,mp4" type="Video" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles />
+  <CodecProfiles />
+  <MediaProfiles />
+</Profile>

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

@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Denon AVR</Name>
+  <Identification>
+    <FriendlyName>Denon:\[AVR:.*</FriendlyName>
+    <Manufacturer>Denon</Manufacturer>
+    <Headers />
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles />
+  <CodecProfiles />
+  <MediaProfiles />
+</Profile>

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

@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>LG Smart TV</Name>
+  <Identification>
+    <FriendlyName>LG.*</FriendlyName>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="LG" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mkv" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="aac,ac3,mp3" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video" codec="mpeg4">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3,aac,mp3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles />
+</Profile>

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

@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Linksys DMA2100</Name>
+  <Identification>
+    <ModelName>DMA2100us</ModelName>
+    <Headers />
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
+    <DirectPlayProfile container="avi,mp4,mkv,ts" type="Video" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles />
+  <CodecProfiles />
+  <MediaProfiles />
+</Profile>

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

@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Panasonic Viera</Name>
+  <Identification>
+    <FriendlyName>VIERA</FriendlyName>
+    <Manufacturer>Panasonic</Manufacturer>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="Panasonic MIL DLNA" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mpeg" audioCodec="ac3,mp3" videoCodec="mpeg2video,mpeg4" type="Video" />
+    <DirectPlayProfile container="mkv" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="aac,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" />
+    <DirectPlayProfile container="flv" audioCodec="aac" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="mp4" audioCodec="aac" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles />
+</Profile>

+ 102 - 0
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml

@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Samsung Smart TV</Name>
+  <Identification>
+    <ModelUrl>samsung.com</ModelUrl>
+    <Headers />
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="asf" audioCodec="mp3,ac3,wmav2,wmapro,wmavoice" videoCodec="h264,mpeg4,mjpeg" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="mp3,ac3,dca" videoCodec="h264,mpeg4,mjpeg" type="Video" />
+    <DirectPlayProfile container="mkv" audioCodec="mp3,ac3,dca,aac" videoCodec="h264,mpeg4,mjpeg4" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="mp3,aac" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="3gpp" audioCodec="aac,he-aac" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="mpg,mpeg" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
+    <DirectPlayProfile container="vro,vob" audioCodec="ac3,mp2,mp3" videoCodec="mpeg1video,mpeg2video" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3,eac3" videoCodec="mpeg2video,h264,vc1" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmavoice" videoCodec="wmv2,wmv3" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video" codec="mpeg2video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="30720000" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="mpeg4">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="8192000" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="37500000" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="wmv2,wmv3,vc1">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="25600000" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3,wmav2,dca,aac,mp3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles>
+    <MediaProfile container="avi" type="Video" mimeType="video/x-msvideo">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="mkv" type="Video" mimeType="video/x-mkv">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

ファイルの差分が大きいため隠しています
+ 19 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml


ファイルの差分が大きいため隠しています
+ 21 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml


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

@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Sony Bravia (2010)</Name>
+  <Identification>
+    <FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName>
+    <Manufacturer>Sony</Manufacturer>
+    <Headers>
+      <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[EHLNPB]X\d[01]\d.*" match="Regex" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Microsoft Corporation</Manufacturer>
+  <ManufacturerUrl>http://www.microsoft.com/</ManufacturerUrl>
+  <ModelName>Windows Media Player Sharing</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>3.0</ModelNumber>
+  <ModelUrl>http://www.microsoft.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <SonyAggregationFlags>10</SonyAggregationFlags>
+  <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</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="20000000" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="mpeg2video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="20000000" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+      </Conditions>
+    </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>
+  <MediaProfiles>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Sony Bravia (2011)</Name>
+  <Identification>
+    <FriendlyName>KDL-\d{2}([A-Z]X\d2\d|CX400).*</FriendlyName>
+    <Manufacturer>Sony</Manufacturer>
+    <Headers>
+      <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}([A-Z]X\d2\d|CX400).*" match="Regex" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Microsoft Corporation</Manufacturer>
+  <ManufacturerUrl>http://www.microsoft.com/</ManufacturerUrl>
+  <ModelName>Windows Media Player Sharing</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>3.0</ModelNumber>
+  <ModelUrl>http://www.microsoft.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <SonyAggregationFlags>10</SonyAggregationFlags>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="20000000" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="mpeg2video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="20000000" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+      </Conditions>
+    </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>
+  <MediaProfiles>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Sony Bravia (2012)</Name>
+  <Identification>
+    <FriendlyName>KDL-\d{2}[A-Z]X\d5(\d|G).*</FriendlyName>
+    <Manufacturer>Sony</Manufacturer>
+    <Headers>
+      <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[A-Z]X\d5(\d|G).*" match="Regex" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Microsoft Corporation</Manufacturer>
+  <ManufacturerUrl>http://www.microsoft.com/</ManufacturerUrl>
+  <ModelName>Windows Media Player Sharing</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>3.0</ModelNumber>
+  <ModelUrl>http://www.microsoft.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <SonyAggregationFlags>10</SonyAggregationFlags>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Sony Bravia (2013)</Name>
+  <Identification>
+    <FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName>
+    <Manufacturer>Sony</Manufacturer>
+    <Headers>
+      <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[WR][5689]\d{2}A.*" match="Regex" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Microsoft Corporation</Manufacturer>
+  <ManufacturerUrl>http://www.microsoft.com/</ManufacturerUrl>
+  <ModelName>Windows Media Player Sharing</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>3.0</ModelNumber>
+  <ModelUrl>http://www.microsoft.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <SonyAggregationFlags>10</SonyAggregationFlags>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
+    <DirectPlayProfile container="mp4" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
+    <DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="ac3,eac3,mp3" videoCodec="mpeg4" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mjpeg" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="mp4" audioCodec="aac" type="Audio" />
+    <DirectPlayProfile container="wav" audioCodec="pcm" type="Audio" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

+ 94 - 0
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Sony PlayStation 3</Name>
+  <Identification>
+    <FriendlyName>PLAYSTATION 3</FriendlyName>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="PLAYSTATION 3" match="Substring" />
+      <HttpHeaderInfo name="X-AV-Client-Info" value="PLAYSTATION 3" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <XDlnaDoc>DMS-1.50</XDlnaDoc>
+  <SonyAggregationFlags>10</SonyAggregationFlags>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,wma" type="Audio" />
+    <DirectPlayProfile container="avi,mp4" type="Video" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="640000" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="wmapro">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="aac">
+      <Conditions>
+        <ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="false" />
+      </Conditions>
+    </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>
+  <MediaProfiles>
+    <MediaProfile container="mp4,mov" audioCodec="aac" type="Video" mimeType="video/mp4">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="avi" type="Video" orgPn="AVI" mimeType="video/divx">
+      <Conditions />
+    </MediaProfile>
+    <MediaProfile container="wav" type="Audio" mimeType="audio/wav">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>WDTV Live</Name>
+  <Identification>
+    <ModelName>WD TV HD Live</ModelName>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="alphanetworks" match="Substring" />
+      <HttpHeaderInfo name="User-Agent" value="ALPHA Networks" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
+    <DirectPlayProfile container="mpeg" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" />
+    <DirectPlayProfile container="mkv" audioCodec="ac3,dca,aac,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="ac3,dca,mp2,mp3" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
+    <DirectPlayProfile container="mp4,mov" audioCodec="ac3,aac,mp2,mp3" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />
+    <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
+    <DirectPlayProfile container="mp4" audioCodec="mp4" type="Audio" />
+    <DirectPlayProfile container="flac" audioCodec="flac" type="Audio" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+    <DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
+    <DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="aac">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles>
+    <MediaProfile container="ts" type="Video" orgPn="MPEG_TS_SD_NA">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Xbox 360</Name>
+  <Identification>
+    <ModelName>Xbox 360</ModelName>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="Xbox" match="Substring" />
+      <HttpHeaderInfo name="User-Agent" value="Xenon" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Microsoft Corporation</Manufacturer>
+  <ManufacturerUrl>http://www.microsoft.com/</ManufacturerUrl>
+  <ModelName>Windows Media Player Sharing</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>12.0</ModelNumber>
+  <ModelUrl>http://www.microsoft.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <XDlnaDoc>DMS-1.50</XDlnaDoc>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
+  <RequiresPlainFolders>true</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
+    <DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
+    <DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
+    <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+    <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+    <DirectPlayProfile container="jpeg" type="Photo" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="asf" type="Video" videoCodec="wmv2" audioCodec="wmav2" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+    <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles>
+    <ContainerProfile type="Video" container="mp4,mov">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Has64BitOffsets" value="false" isRequired="false" />
+      </Conditions>
+    </ContainerProfile>
+    <ContainerProfile type="Photo">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+      </Conditions>
+    </ContainerProfile>
+  </ContainerProfiles>
+  <CodecProfiles>
+    <CodecProfile type="Video" codec="mpeg4">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1280" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="720" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="5120000" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="h264">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="10240000" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="Video" codec="wmv2,wmv3,vc1">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+        <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
+        <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="ac3,wmav2,wmapro">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+    <CodecProfile type="VideoAudio" codec="aac">
+      <Conditions>
+        <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
+        <ProfileCondition condition="Equals" property="AudioProfile" value="lc" isRequired="false" />
+      </Conditions>
+    </CodecProfile>
+  </CodecProfiles>
+  <MediaProfiles>
+    <MediaProfile container="avi" type="Video" mimeType="video/avi">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

+ 41 - 0
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>Xbox One</Name>
+  <Identification>
+    <FriendlyName>Xbox-SystemOS</FriendlyName>
+    <ModelName>Xbox One</ModelName>
+    <Headers />
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,wma" type="Audio" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles />
+  <CodecProfiles />
+  <MediaProfiles>
+    <MediaProfile container="avi" type="Video" mimeType="video/x-msvideo">
+      <Conditions />
+    </MediaProfile>
+  </MediaProfiles>
+</Profile>

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

@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <Name>foobar2000</Name>
+  <Identification>
+    <FriendlyName>foobar</FriendlyName>
+    <Headers>
+      <HttpHeaderInfo name="User-Agent" value="foobar" match="Substring" />
+    </Headers>
+  </Identification>
+  <FriendlyName>Media Browser</FriendlyName>
+  <Manufacturer>Media Browser</Manufacturer>
+  <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+  <ModelName>Media Browser</ModelName>
+  <ModelDescription>Media Browser</ModelDescription>
+  <ModelNumber>Media Browser</ModelNumber>
+  <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+  <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+  <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+  <SupportedMediaTypes>Audio</SupportedMediaTypes>
+  <ProtocolInfo>DLNA</ProtocolInfo>
+  <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+  <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+  <RequiresPlainFolders>false</RequiresPlainFolders>
+  <DirectPlayProfiles>
+    <DirectPlayProfile container="mp3,wma" type="Audio" />
+    <DirectPlayProfile container="avi,mp4" type="Video" />
+  </DirectPlayProfiles>
+  <TranscodingProfiles>
+    <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings />
+    </TranscodingProfile>
+    <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto">
+      <Settings>
+        <TranscodingSetting name="VideoProfile" value="baseline" />
+      </Settings>
+    </TranscodingProfile>
+  </TranscodingProfiles>
+  <ContainerProfiles />
+  <CodecProfiles />
+  <MediaProfiles />
+</Profile>

+ 1 - 1
MediaBrowser.Dlna/Server/Headers.cs

@@ -13,7 +13,7 @@ namespace MediaBrowser.Dlna.Server
         private readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
         private readonly static Regex Validator = new Regex(@"^[a-z\d][a-z\d_.-]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
 
-        protected Headers(bool asIs)
+        public Headers(bool asIs)
         {
             _asIs = asIs;
         }

+ 0 - 16
MediaBrowser.Dlna/Server/RawHeaders.cs

@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Dlna.Server
-{
-    public class RawHeaders : Headers
-    {
-        public RawHeaders()
-            : base(true)
-        {
-        }
-    }
-}

+ 3 - 3
MediaBrowser.Dlna/Server/SsdpHandler.cs

@@ -96,7 +96,7 @@ namespace MediaBrowser.Dlna.Server
                         {
                             break;
                         }
-                        var parts = line.Split(new char[] { ':' }, 2);
+                        var parts = line.Split(new[] { ':' }, 2);
                         headers[parts[0]] = parts[1].Trim();
                     }
 
@@ -148,7 +148,7 @@ namespace MediaBrowser.Dlna.Server
 
         private void SendSearchResponse(IPEndPoint endpoint, UpnpDevice dev)
         {
-            var headers = new RawHeaders();
+            var headers = new Headers(true);
             headers.Add("CACHE-CONTROL", "max-age = 600");
             headers.Add("DATE", DateTime.Now.ToString("R"));
             headers.Add("EXT", "");
@@ -188,7 +188,7 @@ namespace MediaBrowser.Dlna.Server
         private void NotifyDevice(UpnpDevice dev, string type, bool sticky)
         {
             _logger.Debug("NotifyDevice");
-            var headers = new RawHeaders();
+            var headers = new Headers(true);
             headers.Add("HOST", "239.255.255.250:1900");
             headers.Add("CACHE-CONTROL", "max-age = 600");
             headers.Add("LOCATION", dev.Descriptor.ToString());

+ 23 - 21
MediaBrowser.Dlna/PlayTo/SsdpHelper.cs → MediaBrowser.Dlna/Ssdp/SsdpHelper.cs

@@ -1,8 +1,9 @@
 using System;
-using System.Linq;
+using System.Collections.Generic;
+using System.IO;
 using System.Text;
 
-namespace MediaBrowser.Dlna.PlayTo
+namespace MediaBrowser.Dlna.Ssdp
 {
     public class SsdpHelper
     {
@@ -29,28 +30,29 @@ namespace MediaBrowser.Dlna.PlayTo
         /// </summary>
         /// <param name="data">The data.</param>
         /// <returns></returns>
-        public static Uri ParseSsdpResponse(string data)
+        public static Dictionary<string,string> ParseSsdpResponse(byte[] data)
         {
-            var res = (from line in data.Split(new[] { '\r', '\n' })
-                       where line.ToLowerInvariant().StartsWith("location:")
-                       select line).FirstOrDefault();
+            var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
-            return !string.IsNullOrEmpty(res) ? new Uri(res.Substring(9).Trim()) : null;
-        }
-
-        /// <summary>
-        /// Parses data into SSDP event.        
-        /// </summary>
-        /// <param name="data">The data.</param>
-        /// <returns></returns>
-        [Obsolete("Not yet used", true)]
-        public static string ParseSsdpEvent(string data)
-        {
-            var sid = (from line in data.Split(new[] { '\r', '\n' })
-                       where line.ToLowerInvariant().StartsWith("sid:")
-                       select line).FirstOrDefault();
+            using (var reader = new StreamReader(new MemoryStream(data), Encoding.ASCII))
+            {
+                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
+                {
+                    line = line.Trim();
+                    if (string.IsNullOrEmpty(line))
+                    {
+                        break;
+                    }
+                    var parts = line.Split(new[] { ':' }, 2);
 
-            return data;
+                    if (parts.Length == 2)
+                    {
+                        headers[parts[0]] = parts[1].Trim();
+                    }
+                }
+            }
+            
+            return headers;
         }
     }
 }

+ 1 - 1
MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs → MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs

@@ -5,7 +5,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 
-namespace MediaBrowser.Server.Implementations.BdInfo
+namespace MediaBrowser.MediaEncoding.BdInfo
 {
     /// <summary>
     /// Class BdInfoExaminer

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません