aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/LocalizationService.cs9
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs5
-rw-r--r--MediaBrowser.Api/NewsService.cs9
-rw-r--r--MediaBrowser.Api/NotificationsService.cs19
-rw-r--r--MediaBrowser.Api/PackageReviewService.cs22
-rw-r--r--MediaBrowser.Api/PackageService.cs15
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs118
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs50
-rw-r--r--MediaBrowser.Api/Playback/StreamRequest.cs12
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs10
-rw-r--r--MediaBrowser.Api/PluginService.cs21
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs22
-rw-r--r--MediaBrowser.Api/SearchService.cs9
-rw-r--r--MediaBrowser.Api/SessionsService.cs29
-rw-r--r--MediaBrowser.Api/SystemService.cs11
-rw-r--r--MediaBrowser.Api/TvShowsService.cs17
-rw-r--r--MediaBrowser.Api/UserService.cs27
-rw-r--r--MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs18
-rw-r--r--MediaBrowser.Controller/Dlna/CodecProfile.cs18
-rw-r--r--MediaBrowser.Controller/Dlna/ContainerProfile.cs22
-rw-r--r--MediaBrowser.Controller/Dlna/DeviceIdentification.cs10
-rw-r--r--MediaBrowser.Controller/Dlna/DeviceProfile.cs11
-rw-r--r--MediaBrowser.Controller/Dlna/DirectPlayProfile.cs10
-rw-r--r--MediaBrowser.Controller/Dlna/MediaProfile.cs7
-rw-r--r--MediaBrowser.Controller/Dlna/TranscodingProfile.cs23
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Dlna/DlnaManager.cs906
-rw-r--r--MediaBrowser.Dlna/MediaBrowser.Dlna.csproj25
-rw-r--r--MediaBrowser.Dlna/PlayTo/Device.cs5
-rw-r--r--MediaBrowser.Dlna/PlayTo/DeviceInfo.cs5
-rw-r--r--MediaBrowser.Dlna/PlayTo/DlnaController.cs100
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToManager.cs20
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaylistItem.cs22
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs224
-rw-r--r--MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs6
-rw-r--r--MediaBrowser.Dlna/PlayTo/StreamHelper.cs189
-rw-r--r--MediaBrowser.Dlna/Profiles/DefaultProfile.cs59
-rw-r--r--MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs27
-rw-r--r--MediaBrowser.Dlna/Profiles/LgTvProfile.cs192
-rw-r--r--MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs33
-rw-r--r--MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs186
-rw-r--r--MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs315
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs180
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs261
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs286
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs304
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs246
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs264
-rw-r--r--MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs233
-rw-r--r--MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs241
-rw-r--r--MediaBrowser.Dlna/Profiles/Xbox360Profile.cs312
-rw-r--r--MediaBrowser.Dlna/Profiles/XboxOneProfile.cs54
-rw-r--r--MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs115
-rw-r--r--MediaBrowser.Dlna/Server/Headers.cs164
-rw-r--r--MediaBrowser.Dlna/Server/RawHeaders.cs16
-rw-r--r--MediaBrowser.Dlna/Server/SsdpHandler.cs260
-rw-r--r--MediaBrowser.Dlna/Server/UpnpDevice.cs28
-rw-r--r--MediaBrowser.Model/ApiClient/IApiClient.cs2
-rw-r--r--MediaBrowser.Model/Configuration/DlnaOptions.cs6
-rw-r--r--MediaBrowser.Model/Dto/StreamOptions.cs68
-rw-r--r--MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs104
-rw-r--r--MediaBrowser.Model/LiveTv/TimerInfoDto.cs92
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs2
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs4
-rw-r--r--MediaBrowser.WebDashboard/ApiClient.js6
-rw-r--r--MediaBrowser.WebDashboard/packages.config2
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec4
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
71 files changed, 4465 insertions, 1642 deletions
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index b3f6cbd97..60270a389 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -10,8 +10,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetCultures
/// </summary>
- [Route("/Localization/Cultures", "GET")]
- [Api(Description = "Gets known cultures")]
+ [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
public class GetCultures : IReturn<List<CultureDto>>
{
}
@@ -19,8 +18,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetCountries
/// </summary>
- [Route("/Localization/Countries", "GET")]
- [Api(Description = "Gets known countries")]
+ [Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
public class GetCountries : IReturn<List<CountryInfo>>
{
}
@@ -28,8 +26,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class ParentalRatings
/// </summary>
- [Route("/Localization/ParentalRatings", "GET")]
- [Api(Description = "Gets known parental ratings")]
+ [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
public class GetParentalRatings : IReturn<List<ParentalRating>>
{
}
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index f9b760869..204a7aab4 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -117,10 +117,9 @@ namespace MediaBrowser.Api.Movies
public object Get(GetMovieRecommendations request)
{
- var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
+ var user = _userManager.GetUserById(request.UserId.Value);
- var folder = user.RootFolder;
- var movies = folder.RecursiveChildren.OfType<Movie>().ToList();
+ var movies = user.RootFolder.GetRecursiveChildren(user).OfType<Movie>().ToList();
var result = GetRecommendationCategories(user, movies, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList());
diff --git a/MediaBrowser.Api/NewsService.cs b/MediaBrowser.Api/NewsService.cs
index 99a4d4fa7..6243bf25f 100644
--- a/MediaBrowser.Api/NewsService.cs
+++ b/MediaBrowser.Api/NewsService.cs
@@ -5,8 +5,7 @@ using ServiceStack;
namespace MediaBrowser.Api
{
- [Route("/News/Product", "GET")]
- [Api(Description = "Gets the latest product news.")]
+ [Route("/News/Product", "GET", Summary = "Gets the latest product news.")]
public class GetProductNews : IReturn<QueryResult<NewsItem>>
{
/// <summary>
@@ -23,7 +22,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Limit { get; set; }
}
-
+
public class NewsService : BaseApiService
{
private readonly INewsService _newsService;
@@ -37,8 +36,8 @@ namespace MediaBrowser.Api
{
var result = _newsService.GetProductNews(new NewsQuery
{
- StartIndex = request.StartIndex,
- Limit = request.Limit
+ StartIndex = request.StartIndex,
+ Limit = request.Limit
});
diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs
index 45a16347b..a71a85395 100644
--- a/MediaBrowser.Api/NotificationsService.cs
+++ b/MediaBrowser.Api/NotificationsService.cs
@@ -1,15 +1,14 @@
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Notifications;
+using ServiceStack;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using ServiceStack;
namespace MediaBrowser.Api
{
- [Route("/Notifications/{UserId}", "GET")]
- [Api(Description = "Gets notifications")]
+ [Route("/Notifications/{UserId}", "GET", Summary = "Gets notifications")]
public class GetNotifications : IReturn<NotificationResult>
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -25,16 +24,14 @@ namespace MediaBrowser.Api
public int? Limit { get; set; }
}
- [Route("/Notifications/{UserId}/Summary", "GET")]
- [Api(Description = "Gets a notification summary for a user")]
+ [Route("/Notifications/{UserId}/Summary", "GET", Summary = "Gets a notification summary for a user")]
public class GetNotificationsSummary : IReturn<NotificationsSummary>
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid UserId { get; set; }
}
- [Route("/Notifications/{UserId}", "POST")]
- [Api(Description = "Adds a notifications")]
+ [Route("/Notifications/{UserId}", "POST", Summary = "Adds a notifications")]
public class AddUserNotification : IReturn<Notification>
{
[ApiMember(Name = "Id", Description = "The Id of the new notification. If unspecified one will be provided.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
@@ -61,9 +58,8 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Level", Description = "The notification level", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public NotificationLevel Level { get; set; }
}
-
- [Route("/Notifications/{UserId}/Read", "POST")]
- [Api(Description = "Marks notifications as read")]
+
+ [Route("/Notifications/{UserId}/Read", "POST", Summary = "Marks notifications as read")]
public class MarkRead : IReturnVoid
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -73,8 +69,7 @@ namespace MediaBrowser.Api
public string Ids { get; set; }
}
- [Route("/Notifications/{UserId}/Unread", "POST")]
- [Api(Description = "Marks notifications as unread")]
+ [Route("/Notifications/{UserId}/Unread", "POST", Summary = "Marks notifications as unread")]
public class MarkUnread : IReturnVoid
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
diff --git a/MediaBrowser.Api/PackageReviewService.cs b/MediaBrowser.Api/PackageReviewService.cs
index b2de908d9..94ff1b62e 100644
--- a/MediaBrowser.Api/PackageReviewService.cs
+++ b/MediaBrowser.Api/PackageReviewService.cs
@@ -1,21 +1,20 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Constants;
+using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Api
{
/// <summary>
/// Class InstallPackage
/// </summary>
- [Route("/PackageReviews/{Id}", "POST")]
- [Api(("Creates or updates a package review"))]
+ [Route("/Packages/Reviews/{Id}", "POST", Summary = "Creates or updates a package review")]
public class CreateReviewRequest : IReturnVoid
{
/// <summary>
@@ -57,8 +56,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class InstallPackage
/// </summary>
- [Route("/PackageReviews/{Id}", "GET")]
- [Api(("Retrieve reviews for a package"))]
+ [Route("/Packages/{Id}/Reviews", "GET", Summary = "Gets reviews for a package")]
public class ReviewRequest : IReturn<List<PackageReviewInfo>>
{
/// <summary>
@@ -114,7 +112,7 @@ namespace MediaBrowser.Api
public object Get(ReviewRequest request)
{
var parms = "?id=" + request.Id;
-
+
if (request.MaxRating > 0)
{
parms += "&max=" + request.MaxRating;
@@ -132,7 +130,7 @@ namespace MediaBrowser.Api
parms += "&title=true";
}
- var result = _httpClient.Get(Constants.MbAdminUrl + "/service/packageReview/retrieve"+parms, CancellationToken.None).Result;
+ var result = _httpClient.Get(Constants.MbAdminUrl + "/service/packageReview/retrieve" + parms, CancellationToken.None).Result;
var reviews = _serializer.DeserializeFromStream<List<PackageReviewInfo>>(result);
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index 793b666ea..948a67f16 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetPackage
/// </summary>
- [Route("/Packages/{Name}", "GET")]
- [Api(("Gets a package, by name or assembly guid"))]
+ [Route("/Packages/{Name}", "GET", Summary = "Gets a package, by name or assembly guid")]
public class GetPackage : IReturn<PackageInfo>
{
/// <summary>
@@ -36,8 +35,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetPackages
/// </summary>
- [Route("/Packages", "GET")]
- [Api(("Gets available packages"))]
+ [Route("/Packages", "GET", Summary = "Gets available packages")]
public class GetPackages : IReturn<List<PackageInfo>>
{
/// <summary>
@@ -57,8 +55,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetPackageVersionUpdates
/// </summary>
- [Route("/Packages/Updates", "GET")]
- [Api(("Gets available package updates for currently installed packages"))]
+ [Route("/Packages/Updates", "GET", Summary = "Gets available package updates for currently installed packages")]
public class GetPackageVersionUpdates : IReturn<List<PackageVersionInfo>>
{
/// <summary>
@@ -72,8 +69,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class InstallPackage
/// </summary>
- [Route("/Packages/Installed/{Name}", "POST")]
- [Api(("Installs a package"))]
+ [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")]
public class InstallPackage : IReturnVoid
{
/// <summary>
@@ -108,8 +104,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class CancelPackageInstallation
/// </summary>
- [Route("/Packages/Installing/{Id}", "DELETE")]
- [Api(("Cancels a package installation"))]
+ [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")]
public class CancelPackageInstallation : IReturnVoid
{
/// <summary>
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 1001980ec..a6b3b7294 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -9,7 +9,6 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Drawing;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Library;
@@ -735,14 +734,21 @@ namespace MediaBrowser.Api.Playback
{
if (audioStream != null)
{
- if (audioStream.Channels > 2 && request.AudioCodec.HasValue)
+ if (audioStream.Channels > 2 && string.Equals(request.AudioCodec, "wma", StringComparison.OrdinalIgnoreCase))
{
- if (request.AudioCodec.Value == AudioCodecs.Wma)
- {
- // wmav2 currently only supports two channel output
- return 2;
- }
+ // wmav2 currently only supports two channel output
+ return 2;
+ }
+ }
+
+ if (request.MaxAudioChannels.HasValue)
+ {
+ if (audioStream != null && audioStream.Channels.HasValue)
+ {
+ return Math.Min(request.MaxAudioChannels.Value, audioStream.Channels.Value);
}
+
+ return request.MaxAudioChannels.Value;
}
return request.AudioChannels;
@@ -768,26 +774,26 @@ namespace MediaBrowser.Api.Playback
{
var codec = request.AudioCodec;
- if (codec.HasValue)
+ if (!string.IsNullOrEmpty(codec))
{
- if (codec == AudioCodecs.Aac)
+ if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
{
return "aac -strict experimental";
}
- if (codec == AudioCodecs.Mp3)
+ if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
{
return "libmp3lame";
}
- if (codec == AudioCodecs.Vorbis)
+ if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
{
return "libvorbis";
}
- if (codec == AudioCodecs.Wma)
+ if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
{
return "wmav2";
}
- return codec.ToString().ToLower();
+ return codec.ToLower();
}
return "copy";
@@ -802,26 +808,26 @@ namespace MediaBrowser.Api.Playback
{
var codec = request.VideoCodec;
- if (codec.HasValue)
+ if (!string.IsNullOrEmpty(codec))
{
- if (codec == VideoCodecs.H264)
+ if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase))
{
return "libx264";
}
- if (codec == VideoCodecs.Vpx)
+ if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase))
{
return "libvpx";
}
- if (codec == VideoCodecs.Wmv)
+ if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase))
{
return "msmpeg4";
}
- if (codec == VideoCodecs.Theora)
+ if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase))
{
return "libtheora";
}
- return codec.ToString().ToLower();
+ return codec.ToLower();
}
return "copy";
@@ -1201,77 +1207,81 @@ namespace MediaBrowser.Api.Playback
if (i == 0)
{
- request.DeviceId = val;
+ // Device profile name
}
else if (i == 1)
{
- request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ request.DeviceId = val;
}
else if (i == 2)
{
+ request.MediaSourceId = val;
+ }
+ else if (i == 3)
+ {
+ request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+ else if (i == 4)
+ {
if (videoRequest != null)
{
- videoRequest.VideoCodec = (VideoCodecs)Enum.Parse(typeof(VideoCodecs), val, true);
+ videoRequest.VideoCodec = val;
}
}
- else if (i == 3)
+ else if (i == 5)
{
- request.AudioCodec = (AudioCodecs)Enum.Parse(typeof(AudioCodecs), val, true);
+ request.AudioCodec = val;
}
- else if (i == 4)
+ else if (i == 6)
{
if (videoRequest != null)
{
videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
}
}
- else if (i == 5)
+ else if (i == 7)
{
if (videoRequest != null)
{
videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
}
}
- else if (i == 6)
+ else if (i == 8)
{
if (videoRequest != null)
{
videoRequest.VideoBitRate = int.Parse(val, UsCulture);
}
}
- else if (i == 7)
+ else if (i == 9)
{
request.AudioBitRate = int.Parse(val, UsCulture);
}
- else if (i == 8)
+ else if (i == 10)
{
- request.AudioChannels = int.Parse(val, UsCulture);
+ request.MaxAudioChannels = int.Parse(val, UsCulture);
}
- else if (i == 9)
+ else if (i == 11)
{
if (videoRequest != null)
{
request.StartTimeTicks = long.Parse(val, UsCulture);
}
}
- else if (i == 10)
+ else if (i == 12)
{
if (videoRequest != null)
{
videoRequest.Profile = val;
}
}
- else if (i == 11)
+ else if (i == 13)
{
if (videoRequest != null)
{
videoRequest.Level = val;
}
}
- else if (i == 12)
- {
- request.ForcedMimeType = val;
- }
}
}
@@ -1297,7 +1307,7 @@ namespace MediaBrowser.Api.Playback
var url = Request.PathInfo;
- if (!request.AudioCodec.HasValue)
+ if (string.IsNullOrEmpty(request.AudioCodec))
{
request.AudioCodec = InferAudioCodec(url);
}
@@ -1425,7 +1435,7 @@ namespace MediaBrowser.Api.Playback
if (videoRequest != null)
{
- if (!videoRequest.VideoCodec.HasValue)
+ if (string.IsNullOrEmpty(videoRequest.VideoCodec))
{
videoRequest.VideoCodec = InferVideoCodec(url);
}
@@ -1532,41 +1542,41 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="url">The URL.</param>
/// <returns>System.Nullable{AudioCodecs}.</returns>
- private AudioCodecs? InferAudioCodec(string url)
+ private string InferAudioCodec(string url)
{
var ext = Path.GetExtension(url);
if (string.Equals(ext, ".mp3", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Mp3;
+ return "mp3";
}
if (string.Equals(ext, ".aac", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Aac;
+ return "aac";
}
if (string.Equals(ext, ".wma", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Wma;
+ return "wma";
}
if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Vorbis;
+ return "vorbis";
}
if (string.Equals(ext, ".oga", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Vorbis;
+ return "vorbis";
}
if (string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Vorbis;
+ return "vorbis";
}
if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Vorbis;
+ return "vorbis";
}
if (string.Equals(ext, ".webma", StringComparison.OrdinalIgnoreCase))
{
- return AudioCodecs.Vorbis;
+ return "vorbis";
}
return null;
@@ -1577,28 +1587,28 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="url">The URL.</param>
/// <returns>System.Nullable{VideoCodecs}.</returns>
- private VideoCodecs? InferVideoCodec(string url)
+ private string InferVideoCodec(string url)
{
var ext = Path.GetExtension(url);
if (string.Equals(ext, ".asf", StringComparison.OrdinalIgnoreCase))
{
- return VideoCodecs.Wmv;
+ return "wmv";
}
if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase))
{
- return VideoCodecs.Vpx;
+ return "vpx";
}
if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase))
{
- return VideoCodecs.Theora;
+ return "theora";
}
if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase))
{
- return VideoCodecs.H264;
+ return "h264";
}
- return VideoCodecs.Copy;
+ return "copy";
}
}
}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index aec271ff2..eb8f415e0 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -91,11 +91,11 @@ namespace MediaBrowser.Api.Playback.Hls
{
var state = GetState(request, CancellationToken.None).Result;
- if (!state.VideoRequest.VideoBitRate.HasValue && (!state.VideoRequest.VideoCodec.HasValue || state.VideoRequest.VideoCodec.Value != VideoCodecs.Copy))
+ if (!state.VideoRequest.VideoBitRate.HasValue && (string.IsNullOrEmpty(state.VideoRequest.VideoCodec) || !string.Equals(state.VideoRequest.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException("A video bitrate is required");
}
- if (!state.Request.AudioBitRate.HasValue && (!state.Request.AudioCodec.HasValue || state.Request.AudioCodec.Value != AudioCodecs.Copy))
+ if (!state.Request.AudioBitRate.HasValue && (string.IsNullOrEmpty(state.Request.AudioCodec) || !string.Equals(state.Request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException("An audio bitrate is required");
}
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 121957ecc..66e8b0d14 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -136,11 +136,11 @@ namespace MediaBrowser.Api.Playback.Hls
{
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
- if (!state.VideoRequest.VideoBitRate.HasValue && (!state.VideoRequest.VideoCodec.HasValue || state.VideoRequest.VideoCodec.Value != VideoCodecs.Copy))
+ if (!state.VideoRequest.VideoBitRate.HasValue && (string.IsNullOrEmpty(state.VideoRequest.VideoCodec) || !string.Equals(state.VideoRequest.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException("A video bitrate is required");
}
- if (!state.Request.AudioBitRate.HasValue && (!state.Request.AudioCodec.HasValue || state.Request.AudioCodec.Value != AudioCodecs.Copy))
+ if (!state.Request.AudioBitRate.HasValue && (string.IsNullOrEmpty(state.Request.AudioCodec) || !string.Equals(state.Request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException("An audio bitrate is required");
}
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 8ae61b521..9cb989fc2 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -50,39 +50,49 @@ namespace MediaBrowser.Api.Playback.Progressive
var videoRequest = state.Request as VideoStreamRequest;
// Try to infer based on the desired video codec
- if (videoRequest != null && videoRequest.VideoCodec.HasValue)
+ if (videoRequest != null && !string.IsNullOrEmpty(videoRequest.VideoCodec))
{
if (state.IsInputVideo)
{
- switch (videoRequest.VideoCodec.Value)
+ if (string.Equals(videoRequest.VideoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
- case VideoCodecs.H264:
- return ".ts";
- case VideoCodecs.Theora:
- return ".ogv";
- case VideoCodecs.Vpx:
- return ".webm";
- case VideoCodecs.Wmv:
- return ".asf";
+ return ".ts";
+ }
+ if (string.Equals(videoRequest.VideoCodec, "theora", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".ogv";
+ }
+ if (string.Equals(videoRequest.VideoCodec, "vpx", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".webm";
+ }
+ if (string.Equals(videoRequest.VideoCodec, "wmv", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".asf";
}
}
}
// Try to infer based on the desired audio codec
- if (state.Request.AudioCodec.HasValue)
+ if (!string.IsNullOrEmpty(state.Request.AudioCodec))
{
if (!state.IsInputVideo)
{
- switch (state.Request.AudioCodec.Value)
+ if (string.Equals("aac", state.Request.AudioCodec, StringComparison.OrdinalIgnoreCase))
+ {
+ return ".aac";
+ }
+ if (string.Equals("mp3", state.Request.AudioCodec, StringComparison.OrdinalIgnoreCase))
+ {
+ return ".mp3";
+ }
+ if (string.Equals("vorbis", state.Request.AudioCodec, StringComparison.OrdinalIgnoreCase))
+ {
+ return ".ogg";
+ }
+ if (string.Equals("wma", state.Request.AudioCodec, StringComparison.OrdinalIgnoreCase))
{
- case AudioCodecs.Aac:
- return ".aac";
- case AudioCodecs.Mp3:
- return ".mp3";
- case AudioCodecs.Vorbis:
- return ".ogg";
- case AudioCodecs.Wma:
- return ".wma";
+ return ".wma";
}
}
}
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index df52e5e3e..3439621e9 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Model.Dto;
-using ServiceStack;
+using ServiceStack;
namespace MediaBrowser.Api.Playback
{
@@ -26,7 +25,7 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <value>The audio codec.</value>
[ApiMember(Name = "AudioCodec", Description = "Optional. Specify a audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. Options: aac, mp3, vorbis, wma.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public AudioCodecs? AudioCodec { get; set; }
+ public string AudioCodec { get; set; }
/// <summary>
/// Gets or sets the start time ticks.
@@ -49,6 +48,9 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "AudioChannels", Description = "Optional. Specify a specific number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? AudioChannels { get; set; }
+ [ApiMember(Name = "MaxAudioChannels", Description = "Optional. Specify a maximum number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? MaxAudioChannels { get; set; }
+
/// <summary>
/// Gets or sets the audio sample rate.
/// </summary>
@@ -69,8 +71,6 @@ namespace MediaBrowser.Api.Playback
public bool ThrowDebugError { get; set; }
public string Params { get; set; }
-
- public string ForcedMimeType { get; set; }
}
public class VideoStreamRequest : StreamRequest
@@ -80,7 +80,7 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <value>The video codec.</value>
[ApiMember(Name = "VideoCodec", Description = "Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. Options: h264, mpeg4, theora, vpx, wmv.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public VideoCodecs? VideoCodec { get; set; }
+ public string VideoCodec { get; set; }
/// <summary>
/// Gets or sets the video bit rate.
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 88daf9f62..ecc5c93ef 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -79,16 +79,6 @@ namespace MediaBrowser.Api.Playback
public string GetMimeType(string outputPath)
{
- if (!string.IsNullOrWhiteSpace(Request.ForcedMimeType))
- {
- if (VideoRequest == null)
- {
- return "audio/" + Request.ForcedMimeType;
- }
-
- return "video/" + Request.ForcedMimeType;
- }
-
return MimeTypes.GetMimeType(outputPath);
}
}
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs
index e66f432df..31463dc3f 100644
--- a/MediaBrowser.Api/PluginService.cs
+++ b/MediaBrowser.Api/PluginService.cs
@@ -18,8 +18,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class Plugins
/// </summary>
- [Route("/Plugins", "GET")]
- [Api(("Gets a list of currently installed plugins"))]
+ [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
public class GetPlugins : IReturn<List<PluginInfo>>
{
}
@@ -27,8 +26,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UninstallPlugin
/// </summary>
- [Route("/Plugins/{Id}", "DELETE")]
- [Api(("Uninstalls a plugin"))]
+ [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
public class UninstallPlugin : IReturnVoid
{
/// <summary>
@@ -42,8 +40,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetPluginConfiguration
/// </summary>
- [Route("/Plugins/{Id}/Configuration", "GET")]
- [Api(("Gets a plugin's configuration"))]
+ [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")]
public class GetPluginConfiguration
{
/// <summary>
@@ -57,8 +54,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdatePluginConfiguration
/// </summary>
- [Route("/Plugins/{Id}/Configuration", "POST")]
- [Api(("Updates a plugin's configuration"))]
+ [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")]
public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
{
/// <summary>
@@ -78,8 +74,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetPluginSecurityInfo
/// </summary>
- [Route("/Plugins/SecurityInfo", "GET")]
- [Api(("Gets plugin registration information"))]
+ [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information")]
public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
{
}
@@ -87,14 +82,12 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdatePluginSecurityInfo
/// </summary>
- [Route("/Plugins/SecurityInfo", "POST")]
- [Api("Updates plugin registration information")]
+ [Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information")]
public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
{
}
- [Route("/Plugins/RegistrationRecords/{Name}", "GET")]
- [Api("Gets registration status for a feature")]
+ [Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature")]
public class GetRegistrationStatus
{
[ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
index c143635bf..0d3f5dfcd 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
@@ -39,6 +39,8 @@ namespace MediaBrowser.Api.ScheduledTasks
TaskManager = taskManager;
}
+ private bool _lastResponseHadTasksRunning = true;
+
/// <summary>
/// Gets the data to send.
/// </summary>
@@ -46,7 +48,25 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
{
- return Task.FromResult(TaskManager.ScheduledTasks
+ var tasks = TaskManager.ScheduledTasks.ToList();
+
+ var anyRunning = tasks.Any(i => i.State != TaskState.Idle);
+
+ if (anyRunning)
+ {
+ _lastResponseHadTasksRunning = true;
+ }
+ else
+ {
+ if (!_lastResponseHadTasksRunning)
+ {
+ return Task.FromResult<IEnumerable<TaskInfo>>(null);
+ }
+
+ _lastResponseHadTasksRunning = false;
+ }
+
+ return Task.FromResult(tasks
.OrderBy(i => i.Name)
.Select(ScheduledTaskHelpers.GetTaskInfo)
.Where(i => !i.IsHidden));
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index f46c6b8e3..662c728e4 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -1,5 +1,4 @@
-using System;
-using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -8,6 +7,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Search;
using ServiceStack;
+using System;
using System.Linq;
using System.Threading.Tasks;
@@ -16,8 +16,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetSearchHints
/// </summary>
- [Route("/Search/Hints", "GET")]
- [Api(Description = "Gets search hints based on a search term")]
+ [Route("/Search/Hints", "GET", Summary = "Gets search hints based on a search term")]
public class GetSearchHints : IReturn<SearchHintResult>
{
/// <summary>
@@ -66,7 +65,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; }
-
+
public GetSearchHints()
{
IncludeArtists = true;
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index e73e3490e..a509c876c 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetSessions
/// </summary>
- [Route("/Sessions", "GET")]
- [Api(("Gets a list of sessions"))]
+ [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
public class GetSessions : IReturn<List<SessionInfoDto>>
{
/// <summary>
@@ -28,15 +27,14 @@ namespace MediaBrowser.Api
[ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public Guid? ControllableByUserId { get; set; }
- [ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
+ [ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; }
}
/// <summary>
/// Class BrowseTo
/// </summary>
- [Route("/Sessions/{Id}/Viewing", "POST")]
- [Api(("Instructs a session to browse to an item or view"))]
+ [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")]
public class BrowseTo : IReturnVoid
{
/// <summary>
@@ -77,8 +75,7 @@ namespace MediaBrowser.Api
public string Context { get; set; }
}
- [Route("/Sessions/{Id}/Playing", "POST")]
- [Api(("Instructs a session to play an item"))]
+ [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")]
public class Play : IReturnVoid
{
/// <summary>
@@ -110,8 +107,7 @@ namespace MediaBrowser.Api
public PlayCommand PlayCommand { get; set; }
}
- [Route("/Sessions/{Id}/Playing/{Command}", "POST")]
- [Api(("Issues a playstate command to a client"))]
+ [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
public class SendPlaystateCommand : IReturnVoid
{
/// <summary>
@@ -135,8 +131,7 @@ namespace MediaBrowser.Api
public PlaystateCommand Command { get; set; }
}
- [Route("/Sessions/{Id}/System/{Command}", "POST")]
- [Api(("Issues a system command to a client"))]
+ [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
public class SendSystemCommand : IReturnVoid
{
/// <summary>
@@ -154,8 +149,7 @@ namespace MediaBrowser.Api
public SystemCommand Command { get; set; }
}
- [Route("/Sessions/{Id}/Message", "POST")]
- [Api(("Issues a command to a client to display a message to the user"))]
+ [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
public class SendMessageCommand : IReturnVoid
{
/// <summary>
@@ -175,8 +169,7 @@ namespace MediaBrowser.Api
public long? TimeoutMs { get; set; }
}
- [Route("/Sessions/{Id}/Users/{UserId}", "POST")]
- [Api(("Adds an additional user to a session"))]
+ [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")]
public class AddUserToSession : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -186,8 +179,7 @@ namespace MediaBrowser.Api
public Guid UserId { get; set; }
}
- [Route("/Sessions/{Id}/Users/{UserId}", "DELETE")]
- [Api(("Removes an additional user from a session"))]
+ [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")]
public class RemoveUserFromSession : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -197,8 +189,7 @@ namespace MediaBrowser.Api
public Guid UserId { get; set; }
}
- [Route("/Sessions/{Id}/Capabilities", "POST")]
- [Api(("Updates capabilities for a device"))]
+ [Route("/Sessions/{Id}/Capabilities", "POST", Summary = "Updates capabilities for a device")]
public class PostCapabilities : IReturnVoid
{
/// <summary>
diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs
index 9f5f3716e..2f0741434 100644
--- a/MediaBrowser.Api/SystemService.cs
+++ b/MediaBrowser.Api/SystemService.cs
@@ -8,8 +8,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetSystemInfo
/// </summary>
- [Route("/System/Info", "GET")]
- [Api(Description = "Gets information about the server")]
+ [Route("/System/Info", "GET", Summary = "Gets information about the server")]
public class GetSystemInfo : IReturn<SystemInfo>
{
@@ -18,18 +17,16 @@ namespace MediaBrowser.Api
/// <summary>
/// Class RestartApplication
/// </summary>
- [Route("/System/Restart", "POST")]
- [Api(("Restarts the application, if needed"))]
+ [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
public class RestartApplication
{
}
- [Route("/System/Shutdown", "POST")]
- [Api(("Shuts down the application"))]
+ [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")]
public class ShutdownApplication
{
}
-
+
/// <summary>
/// Class SystemInfoService
/// </summary>
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index a805b7b55..7fa586a7d 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetNextUpEpisodes
/// </summary>
- [Route("/Shows/NextUp", "GET")]
- [Api(("Gets a list of next up episodes"))]
+ [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")]
public class GetNextUpEpisodes : IReturn<ItemsResult>, IHasItemFields
{
/// <summary>
@@ -53,8 +52,7 @@ namespace MediaBrowser.Api
public string SeriesId { get; set; }
}
- [Route("/Shows/Upcoming", "GET")]
- [Api(("Gets a list of upcoming episodes"))]
+ [Route("/Shows/Upcoming", "GET", Summary = "Gets a list of upcoming episodes")]
public class GetUpcomingEpisodes : IReturn<ItemsResult>, IHasItemFields
{
/// <summary>
@@ -86,14 +84,12 @@ namespace MediaBrowser.Api
public string Fields { get; set; }
}
- [Route("/Shows/{Id}/Similar", "GET")]
- [Api(Description = "Finds tv shows similar to a given one.")]
+ [Route("/Shows/{Id}/Similar", "GET", Summary = "Finds tv shows similar to a given one.")]
public class GetSimilarShows : BaseGetSimilarItemsFromItem
{
}
- [Route("/Shows/{Id}/Episodes", "GET")]
- [Api(Description = "Gets episodes for a tv season")]
+ [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")]
public class GetEpisodes : IReturn<ItemsResult>, IHasItemFields
{
/// <summary>
@@ -129,8 +125,7 @@ namespace MediaBrowser.Api
public string AdjacentTo { get; set; }
}
- [Route("/Shows/{Id}/Seasons", "GET")]
- [Api(Description = "Gets seasons for a tv series")]
+ [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")]
public class GetSeasons : IReturn<ItemsResult>, IHasItemFields
{
/// <summary>
@@ -320,7 +315,7 @@ namespace MediaBrowser.Api
return 0;
})
- .ThenByDescending(i =>i.Item2)
+ .ThenByDescending(i => i.Item2)
.ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
.Select(i => i.Item1);
}
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 18c3bd096..2f1b16107 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetUsers
/// </summary>
- [Route("/Users", "GET")]
- [Api(Description = "Gets a list of users")]
+ [Route("/Users", "GET", Summary = "Gets a list of users")]
public class GetUsers : IReturn<List<UserDto>>
{
[ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -28,8 +27,7 @@ namespace MediaBrowser.Api
public bool? IsDisabled { get; set; }
}
- [Route("/Users/Public", "GET")]
- [Api(Description = "Gets a list of publicly visible users for display on a login screen.")]
+ [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
public class GetPublicUsers : IReturn<List<UserDto>>
{
}
@@ -37,8 +35,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetUser
/// </summary>
- [Route("/Users/{Id}", "GET")]
- [Api(Description = "Gets a user by Id")]
+ [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
public class GetUser : IReturn<UserDto>
{
/// <summary>
@@ -52,8 +49,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class DeleteUser
/// </summary>
- [Route("/Users/{Id}", "DELETE")]
- [Api(Description = "Deletes a user")]
+ [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
public class DeleteUser : IReturnVoid
{
/// <summary>
@@ -67,8 +63,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class AuthenticateUser
/// </summary>
- [Route("/Users/{Id}/Authenticate", "POST")]
- [Api(Description = "Authenticates a user")]
+ [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")]
public class AuthenticateUser : IReturn<AuthenticationResult>
{
/// <summary>
@@ -89,8 +84,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class AuthenticateUser
/// </summary>
- [Route("/Users/AuthenticateByName", "POST")]
- [Api(Description = "Authenticates a user")]
+ [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")]
public class AuthenticateUserByName : IReturn<AuthenticationResult>
{
/// <summary>
@@ -111,8 +105,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdateUserPassword
/// </summary>
- [Route("/Users/{Id}/Password", "POST")]
- [Api(Description = "Updates a user's password")]
+ [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")]
public class UpdateUserPassword : IReturnVoid
{
/// <summary>
@@ -143,8 +136,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdateUser
/// </summary>
- [Route("/Users/{Id}", "POST")]
- [Api(Description = "Updates a user")]
+ [Route("/Users/{Id}", "POST", Summary = "Updates a user")]
public class UpdateUser : UserDto, IReturnVoid
{
}
@@ -152,8 +144,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class CreateUser
/// </summary>
- [Route("/Users", "POST")]
- [Api(Description = "Creates a user")]
+ [Route("/Users", "POST", Summary = "Creates a user")]
public class CreateUser : UserDto, IReturn<UserDto>
{
}
diff --git a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
index 4ff34cfa1..33d3f368b 100644
--- a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
@@ -1,11 +1,11 @@
-using System.Globalization;
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Net;
namespace MediaBrowser.Common.Net
{
@@ -16,6 +16,7 @@ namespace MediaBrowser.Common.Net
/// <typeparam name="TStateType">The type of the T state type.</typeparam>
public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable
where TStateType : class, new()
+ where TReturnDataType : class
{
/// <summary>
/// The _active connections
@@ -144,12 +145,15 @@ namespace MediaBrowser.Common.Net
var data = await GetDataToSend(tuple.Item4).ConfigureAwait(false);
- await connection.SendAsync(new WebSocketMessage<TReturnDataType>
+ if (data != null)
{
- MessageType = Name,
- Data = data
+ await connection.SendAsync(new WebSocketMessage<TReturnDataType>
+ {
+ MessageType = Name,
+ Data = data
- }, tuple.Item2.Token).ConfigureAwait(false);
+ }, tuple.Item2.Token).ConfigureAwait(false);
+ }
tuple.Item5.Release();
}
diff --git a/MediaBrowser.Controller/Dlna/CodecProfile.cs b/MediaBrowser.Controller/Dlna/CodecProfile.cs
index bff374298..5621c7ef2 100644
--- a/MediaBrowser.Controller/Dlna/CodecProfile.cs
+++ b/MediaBrowser.Controller/Dlna/CodecProfile.cs
@@ -6,12 +6,12 @@ namespace MediaBrowser.Controller.Dlna
public class CodecProfile
{
public CodecType Type { get; set; }
- public List<ProfileCondition> Conditions { get; set; }
+ public ProfileCondition[] Conditions { get; set; }
public string Codec { get; set; }
public CodecProfile()
{
- Conditions = new List<ProfileCondition>();
+ Conditions = new ProfileCondition[] {};
}
public List<string> GetCodecs()
@@ -32,6 +32,12 @@ namespace MediaBrowser.Controller.Dlna
public ProfileConditionType Condition { get; set; }
public ProfileConditionValue Property { get; set; }
public string Value { get; set; }
+ public bool IsRequired { get; set; }
+
+ public ProfileCondition()
+ {
+ IsRequired = true;
+ }
}
public enum ProfileConditionType
@@ -46,11 +52,17 @@ namespace MediaBrowser.Controller.Dlna
{
AudioChannels,
AudioBitrate,
+ AudioProfile,
Filesize,
Width,
Height,
+ Has64BitOffsets,
+ VideoBitDepth,
VideoBitrate,
VideoFramerate,
- VideoLevel
+ VideoLevel,
+ VideoPacketLength,
+ VideoProfile,
+ VideoTimestamp
}
}
diff --git a/MediaBrowser.Controller/Dlna/ContainerProfile.cs b/MediaBrowser.Controller/Dlna/ContainerProfile.cs
new file mode 100644
index 000000000..3bd3c9eaf
--- /dev/null
+++ b/MediaBrowser.Controller/Dlna/ContainerProfile.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Controller.Dlna
+{
+ public class ContainerProfile
+ {
+ public DlnaProfileType Type { get; set; }
+ public ProfileCondition[] Conditions { get; set; }
+ public string Container { get; set; }
+
+ public ContainerProfile()
+ {
+ Conditions = new ProfileCondition[] { };
+ }
+
+ public List<string> GetContainers()
+ {
+ return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Dlna/DeviceIdentification.cs b/MediaBrowser.Controller/Dlna/DeviceIdentification.cs
index 20c94ad50..461c77537 100644
--- a/MediaBrowser.Controller/Dlna/DeviceIdentification.cs
+++ b/MediaBrowser.Controller/Dlna/DeviceIdentification.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-
+
namespace MediaBrowser.Controller.Dlna
{
public class DeviceIdentification
@@ -55,11 +54,11 @@ namespace MediaBrowser.Controller.Dlna
/// Gets or sets the headers.
/// </summary>
/// <value>The headers.</value>
- public List<HttpHeaderInfo> Headers { get; set; }
+ public HttpHeaderInfo[] Headers { get; set; }
public DeviceIdentification()
{
- Headers = new List<HttpHeaderInfo>();
+ Headers = new HttpHeaderInfo[] {};
}
}
@@ -73,6 +72,7 @@ namespace MediaBrowser.Controller.Dlna
public enum HeaderMatchType
{
Equals = 0,
- Substring = 1
+ Regex = 1,
+ Substring = 2
}
}
diff --git a/MediaBrowser.Controller/Dlna/DeviceProfile.cs b/MediaBrowser.Controller/Dlna/DeviceProfile.cs
index 91be73bba..f3de1bc34 100644
--- a/MediaBrowser.Controller/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Controller/Dlna/DeviceProfile.cs
@@ -20,13 +20,15 @@ namespace MediaBrowser.Controller.Dlna
/// </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; }
+ public ContainerProfile[] ContainerProfiles { get; set; }
+
/// <summary>
/// Gets or sets the identification.
/// </summary>
@@ -40,6 +42,9 @@ namespace MediaBrowser.Controller.Dlna
public string ModelDescription { get; set; }
public string ModelNumber { get; set; }
public string ModelUrl { get; set; }
+ public bool IgnoreTranscodeByteRangeRequests { get; set; }
+ public bool SupportsAlbumArtInDidl { get; set; }
+
/// <summary>
/// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
/// </summary>
@@ -60,12 +65,16 @@ namespace MediaBrowser.Controller.Dlna
public int TimelineOffsetSeconds { get; set; }
+ public bool RequiresPlainVideoItems { get; set; }
+ public bool RequiresPlainFolders { get; set; }
+
public DeviceProfile()
{
DirectPlayProfiles = new DirectPlayProfile[] { };
TranscodingProfiles = new TranscodingProfile[] { };
MediaProfiles = new MediaProfile[] { };
CodecProfiles = new CodecProfile[] { };
+ ContainerProfiles = new ContainerProfile[] { };
}
}
}
diff --git a/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs b/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs
index 53d32a2f8..686b31287 100644
--- a/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs
+++ b/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs
@@ -5,19 +5,15 @@ namespace MediaBrowser.Controller.Dlna
{
public class DirectPlayProfile
{
- public string[] Containers { get; set; }
+ public string Container { get; set; }
public string AudioCodec { get; set; }
public string VideoCodec { get; set; }
public DlnaProfileType Type { get; set; }
- public List<ProfileCondition> Conditions { get; set; }
-
- public DirectPlayProfile()
+ public List<string> GetContainers()
{
- Conditions = new List<ProfileCondition>();
-
- Containers = new string[] { };
+ return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
}
public List<string> GetAudioCodecs()
diff --git a/MediaBrowser.Controller/Dlna/MediaProfile.cs b/MediaBrowser.Controller/Dlna/MediaProfile.cs
index 5fa41b18a..1d2613fac 100644
--- a/MediaBrowser.Controller/Dlna/MediaProfile.cs
+++ b/MediaBrowser.Controller/Dlna/MediaProfile.cs
@@ -13,6 +13,13 @@ namespace MediaBrowser.Controller.Dlna
public string OrgPn { get; set; }
public string MimeType { get; set; }
+ public ProfileCondition[] Conditions { get; set; }
+
+ public MediaProfile()
+ {
+ Conditions = new ProfileCondition[] {};
+ }
+
public List<string> GetAudioCodecs()
{
return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
diff --git a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs
index 530a44b8c..1ce2adb1b 100644
--- a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs
+++ b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-
+
namespace MediaBrowser.Controller.Dlna
{
public class TranscodingProfile
@@ -11,12 +10,18 @@ namespace MediaBrowser.Controller.Dlna
public string VideoCodec { get; set; }
public string AudioCodec { get; set; }
- public List<TranscodingSetting> Settings { get; set; }
+ public bool EstimateContentLength { get; set; }
+
+ public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
+
+ public TranscodingSetting[] Settings { get; set; }
public TranscodingProfile()
{
- Settings = new List<TranscodingSetting>();
+ Settings = new TranscodingSetting[] { };
}
+
+ public bool EnableMpegtsM2TsMode { get; set; }
}
public class TranscodingSetting
@@ -27,6 +32,14 @@ namespace MediaBrowser.Controller.Dlna
public enum TranscodingSettingType
{
- Profile
+ VideoLevel = 0,
+ VideoProfile = 1,
+ MaxAudioChannels = 2
+ }
+
+ public enum TranscodeSeekInfo
+ {
+ Auto = 0,
+ Bytes = 1
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index b51824bdb..5e6297d06 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -79,6 +79,7 @@
<Compile Include="Collections\CollectionCreationOptions.cs" />
<Compile Include="Collections\ICollectionManager.cs" />
<Compile Include="Dlna\CodecProfile.cs" />
+ <Compile Include="Dlna\ContainerProfile.cs" />
<Compile Include="Dlna\DeviceIdentification.cs" />
<Compile Include="Dlna\DirectPlayProfile.cs" />
<Compile Include="Dlna\IDlnaManager.cs" />
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index be7295e12..c6da865cd 100644
--- a/MediaBrowser.Dlna/DlnaManager.cs
+++ b/MediaBrowser.Dlna/DlnaManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Dlna.Profiles;
using MediaBrowser.Model.Serialization;
using System.Collections.Generic;
using System.Linq;
@@ -13,849 +14,42 @@ namespace MediaBrowser.Dlna
private IApplicationPaths _appPaths;
private readonly IXmlSerializer _xmlSerializer;
private readonly IFileSystem _fileSystem;
+ private readonly IJsonSerializer _jsonSerializer;
- public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem)
+ public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
{
_xmlSerializer = xmlSerializer;
_fileSystem = fileSystem;
+ _jsonSerializer = jsonSerializer;
- //GetProfiles();
+ GetProfiles();
}
public IEnumerable<DeviceProfile> GetProfiles()
{
- var list = new List<DeviceProfile>();
-
- list.Add(new DeviceProfile
- {
- Name = "Samsung TV (B Series)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = "^TV$",
- ModelNumber = @"1\.0",
- ModelName = "Samsung DTV DMR"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio,
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio,
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/x-msvideo",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="mkv",
- MimeType = "video/x-mkv",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Samsung TV (E/F-series)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"(^\[TV\][A-Z]{2}\d{2}(E|F)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung|(^\[TV\]Samsung [A-Z]{2}\d{2}(E|F)[A-Z]?\d{3,4}.*)",
- ModelNumber = @"(1\.0)|(AllShare1\.0)"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/x-msvideo",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="mkv",
- MimeType = "video/x-mkv",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Samsung TV (C/D-series)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"(^TV-\d{2}C\d{3}.*)|(^\[TV\][A-Z]{2}\d{2}(D)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung",
- ModelNumber = @"(1\.0)|(AllShare1\.0)"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/x-msvideo",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="mkv",
- MimeType = "video/x-mkv",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Xbox 360",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- ModelName = "Xbox 360"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Xbox One",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- ModelName = "Xbox One",
- FriendlyName = "Xbox-SystemOS"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/x-msvideo",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Sony Bravia (2012)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"BRAVIA KDL-\d{2}[A-Z]X\d5(\d|G).*"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- Type = DlnaProfileType.Audio
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="asf",
- MimeType = "video/x-ms-wmv",
- Type = DlnaProfileType.Audio
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Sony Bravia (2013)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"BRAVIA (KDL-\d{2}W[689]\d{2}A.*)|(KD-\d{2}X9\d{3}A.*)"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"wma"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="mp4",
- MimeType = "video/mp4",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="ts",
- MimeType = "video/mpeg",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="wma",
- MimeType = "video/x-ms-wma",
- Type = DlnaProfileType.Audio
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- //Panasonic Viera (2011|2012) Without AVI Support
- Name = "Panasonic Viera E/S/ST/VT (2011)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"(VIERA (E|S)T?(3|5)0?.*)|(VIERA VT30.*)",
- Manufacturer = "Panasonic"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- //Panasonic Viera (2011|2012) With AVI Support
- Name = "Panasonic Viera G/GT/DT/UT/VT (2011/2012)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"(VIERA (G|D|U)T?(3|5)0?.*)|(VIERA VT50.*)",
- Manufacturer = "Panasonic"
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/divx",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Philips (2010-)",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = ".*PHILIPS.*",
- ModelName = "WD TV HD Live"
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3", "wma"},
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- },
-
- new MediaProfile
- {
- Container ="mkv",
- MimeType = "video/x-matroska",
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "WDTV Live",
- ClientType = "DLNA",
-
- TimelineOffsetSeconds = 5,
-
- Identification = new DeviceIdentification
- {
- ModelName = "WD TV HD Live",
-
- Headers = new List<HttpHeaderInfo>
- {
- new HttpHeaderInfo{ Name="User-Agent", Value="alphanetworks", Match= HeaderMatchType.Substring},
- new HttpHeaderInfo{ Name="User-Agent", Value="ALPHA Networks", Match= HeaderMatchType.Substring}
- }
- },
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio,
- AudioCodec = "mp3"
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video,
- VideoCodec = "h264",
- AudioCodec = "aac"
- },
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- Type = DlnaProfileType.Video,
- VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
- AudioCodec = "ac3,dca,mp2,mp3,pcm"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mpeg"},
- Type = DlnaProfileType.Video,
- VideoCodec = "mpeg1video,mpeg2video",
- AudioCodec = "ac3,dca,mp2,mp3,pcm"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mkv"},
- Type = DlnaProfileType.Video,
- VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
- AudioCodec = "ac3,dca,aac,mp2,mp3,pcm"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"ts"},
- Type = DlnaProfileType.Video,
- VideoCodec = "mpeg1video,mpeg2video,h264,vc1",
- AudioCodec = "ac3,dca,mp2,mp3"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mp4", "mov"},
- Type = DlnaProfileType.Video,
- VideoCodec = "h264,mpeg4",
- AudioCodec = "ac3,aac,mp2,mp3"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- Type = DlnaProfileType.Video,
- VideoCodec = "vc1",
- AudioCodec = "wmav2,wmapro"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- Type = DlnaProfileType.Video,
- VideoCodec = "mpeg2video",
- AudioCodec = "mp2,ac3"
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- AudioCodec = "mp2,mp3",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"mp4"},
- AudioCodec = "mp4",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"flac"},
- AudioCodec = "flac",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- AudioCodec = "wmav2,wmapro,wmavoice",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"ogg"},
- AudioCodec = "vorbis",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Type = DlnaProfileType.Photo,
-
- Containers = new[]{"jpeg", "png", "gif", "bmp", "tiff"},
-
- Conditions = new List<ProfileCondition>
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Width, Value = "1920"},
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080"}
- }
- }
- },
-
- MediaProfiles = new[]
- {
- new MediaProfile
- {
- Container ="ts",
- OrgPn = "MPEG_TS_SD_NA",
- Type = DlnaProfileType.Video
- }
- },
-
- CodecProfiles = new[]
- {
- new CodecProfile
- {
- Type = CodecType.VideoCodec,
- Codec= "h264",
-
- Conditions = new List<ProfileCondition>
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Width, Value = "1920"},
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080"},
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.VideoLevel, Value = "41"}
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.VideoAudioCodec,
- Codec= "aac",
-
- Conditions = new List<ProfileCondition>
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.AudioChannels, Value = "2"}
- }
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- // Linksys DMA2100us does not need any transcoding of the formats we support statically
- Name = "Linksys DMA2100",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- ModelName = "DMA2100us"
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3", "flac", "m4a", "wma"},
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"avi", "mp4", "mkv", "ts"},
- Type = DlnaProfileType.Video
- }
- }
- });
-
- list.Add(new DeviceProfile
- {
- Name = "Denon AVR",
- ClientType = "DLNA",
-
- Identification = new DeviceIdentification
- {
- FriendlyName = @"Denon:\[AVR:.*",
- Manufacturer = "Denon"
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3", "flac", "m4a", "wma"},
- Type = DlnaProfileType.Audio
- },
- }
- });
+ var list = new List<DeviceProfile>
+ {
+ new SamsungSmartTvProfile(),
+ new Xbox360Profile(),
+ new XboxOneProfile(),
+ new SonyPs3Profile(),
+ new SonyBravia2010Profile(),
+ new SonyBravia2011Profile(),
+ new SonyBravia2012Profile(),
+ new SonyBravia2013Profile(),
+ new SonyBlurayPlayer2013Profile(),
+ new SonyBlurayPlayerProfile(),
+ new PanasonicVieraProfile(),
+ new WdtvLiveProfile(),
+ new DenonAvrProfile(),
+ new LinksysDMA2100Profile(),
+ new LgTvProfile()
+ };
foreach (var item in list)
{
- //_xmlSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name));
+ //_xmlSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".xml");
+ //_jsonSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".json");
}
return list;
@@ -863,37 +57,7 @@ namespace MediaBrowser.Dlna
public DeviceProfile GetDefaultProfile()
{
- return new DeviceProfile
- {
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"mp3", "wma"},
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Containers = new[]{"avi", "mp4"},
- Type = DlnaProfileType.Video
- }
- }
- };
+ return new DefaultProfile();
}
public DeviceProfile GetProfile(DeviceIdentification deviceInfo)
@@ -906,55 +70,55 @@ namespace MediaBrowser.Dlna
{
if (!string.IsNullOrWhiteSpace(profileInfo.DeviceDescription))
{
- if (!Regex.IsMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription))
+ if (deviceInfo.DeviceDescription == null || !Regex.IsMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.FriendlyName))
{
- if (!Regex.IsMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName))
+ if (deviceInfo.FriendlyName == null || !Regex.IsMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.Manufacturer))
{
- if (!Regex.IsMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer))
+ if (deviceInfo.Manufacturer == null || !Regex.IsMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.ManufacturerUrl))
{
- if (!Regex.IsMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl))
+ if (deviceInfo.ManufacturerUrl == null || !Regex.IsMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.ModelDescription))
{
- if (!Regex.IsMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription))
+ if (deviceInfo.ModelDescription == null || !Regex.IsMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.ModelName))
{
- if (!Regex.IsMatch(deviceInfo.ModelName, profileInfo.ModelName))
+ if (deviceInfo.ModelName == null || !Regex.IsMatch(deviceInfo.ModelName, profileInfo.ModelName))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.ModelNumber))
{
- if (!Regex.IsMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber))
+ if (deviceInfo.ModelNumber == null || !Regex.IsMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.ModelUrl))
{
- if (!Regex.IsMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl))
+ if (deviceInfo.ModelUrl == null || !Regex.IsMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl))
return false;
}
if (!string.IsNullOrWhiteSpace(profileInfo.SerialNumber))
{
- if (!Regex.IsMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber))
+ if (deviceInfo.SerialNumber == null || !Regex.IsMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber))
return false;
}
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index 800fb1b23..bea281b61 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -81,7 +81,28 @@
<Compile Include="PlayTo\uIcon.cs" />
<Compile Include="PlayTo\uParser.cs" />
<Compile Include="PlayTo\uPnpNamespaces.cs" />
+ <Compile Include="Profiles\DefaultProfile.cs" />
+ <Compile Include="Profiles\DenonAvrProfile.cs" />
+ <Compile Include="Profiles\LgTvProfile.cs" />
+ <Compile Include="Profiles\LinksysDMA2100Profile.cs" />
+ <Compile Include="Profiles\PanasonicVieraProfile.cs" />
+ <Compile Include="Profiles\SamsungSmartTvProfile.cs" />
+ <Compile Include="Profiles\SonyBlurayPlayer2013Profile.cs" />
+ <Compile Include="Profiles\SonyBlurayPlayerProfile.cs" />
+ <Compile Include="Profiles\SonyBravia2010Profile.cs" />
+ <Compile Include="Profiles\SonyBravia2011Profile.cs" />
+ <Compile Include="Profiles\SonyBravia2012Profile.cs" />
+ <Compile Include="Profiles\SonyBravia2013Profile.cs" />
+ <Compile Include="Profiles\SonyPs3Profile.cs" />
+ <Compile Include="Profiles\WdtvLiveProfile.cs" />
+ <Compile Include="Profiles\Xbox360Profile.cs" />
+ <Compile Include="Profiles\XboxOneProfile.cs" />
<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>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
@@ -97,9 +118,7 @@
<Name>MediaBrowser.Model</Name>
</ProjectReference>
</ItemGroup>
- <ItemGroup>
- <Folder Include="Server\" />
- </ItemGroup>
+ <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.
diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs
index 5952a213a..2b43c019c 100644
--- a/MediaBrowser.Dlna/PlayTo/Device.cs
+++ b/MediaBrowser.Dlna/PlayTo/Device.cs
@@ -681,7 +681,10 @@ 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;
+
deviceProperties.BaseUrl = String.Format("http://{0}:{1}", url.Host, url.Port);
diff --git a/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs
index 4b40daf70..c57e95c19 100644
--- a/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs
+++ b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs
@@ -34,6 +34,8 @@ namespace MediaBrowser.Dlna.PlayTo
public string ModelNumber { get; set; }
+ public string ModelUrl { get; set; }
+
public string Manufacturer { get; set; }
public string ManufacturerUrl { get; set; }
@@ -72,7 +74,8 @@ namespace MediaBrowser.Dlna.PlayTo
ModelName = ModelName,
ModelNumber = ModelNumber,
FriendlyName = Name,
- ManufacturerUrl = ManufacturerUrl
+ ManufacturerUrl = ManufacturerUrl,
+ ModelUrl = ModelUrl
};
}
}
diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs
index e94663802..ecda07f0b 100644
--- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs
+++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs
@@ -270,7 +270,7 @@ namespace MediaBrowser.Dlna.PlayTo
playlistItem.StartPositionTicks = newItem.StartPositionTicks;
playlistItem.StreamUrl = newItem.StreamUrl;
playlistItem.Didl = newItem.Didl;
- return _device.SetAvTransport(playlistItem.StreamUrl, playlistItem.DlnaHeaders, playlistItem.Didl);
+ return _device.SetAvTransport(playlistItem.StreamUrl, GetDlnaHeaders(playlistItem), playlistItem.Didl);
}
return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0));
@@ -391,16 +391,23 @@ namespace MediaBrowser.Dlna.PlayTo
private PlaylistItem CreatePlaylistItem(BaseItem item, long startPostionTicks, string serverAddress)
{
- var streams = _itemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = item.Id }).ToList();
+ var streams = _itemRepository.GetMediaStreams(new MediaStreamQuery
+ {
+ ItemId = item.Id
+
+ }).ToList();
var deviceInfo = _device.Properties;
- var playlistItem = GetPlaylistItem(item, _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()));
+ var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification());
+
+ var playlistItem = GetPlaylistItem(item, streams, profile);
playlistItem.StartPositionTicks = startPostionTicks;
+ playlistItem.DeviceProfileName = profile.Name;
if (playlistItem.MediaType == DlnaProfileType.Audio)
{
- playlistItem.StreamUrl = StreamHelper.GetAudioUrl(playlistItem, serverAddress);
+ playlistItem.StreamUrl = StreamHelper.GetAudioUrl(deviceInfo, playlistItem, streams, serverAddress);
}
else
{
@@ -410,32 +417,92 @@ namespace MediaBrowser.Dlna.PlayTo
var didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams);
playlistItem.Didl = didl;
- var header = StreamHelper.GetDlnaHeaders(playlistItem);
- playlistItem.DlnaHeaders = header;
return playlistItem;
}
- private PlaylistItem GetPlaylistItem(BaseItem item, DeviceProfile profile)
+ private string GetDlnaHeaders(PlaylistItem item)
+ {
+ var orgOp = item.Transcode ? ";DLNA.ORG_OP=00" : ";DLNA.ORG_OP=01";
+
+ var orgCi = item.Transcode ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
+
+ const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
+
+ string contentFeatures;
+
+ var container = item.Container.TrimStart('.');
+
+ if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=MP3";
+ }
+ else if (string.Equals(container, "wma", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=WMABASE";
+ }
+ else if (string.Equals(container, "wmw", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
+ }
+ else if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
+ }
+ else if (string.Equals(container, "avi", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=AVI";
+ }
+ else if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=MATROSKA";
+ }
+ else if (string.Equals(container, "mp4", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
+ }
+ else if (string.Equals(container, "mpeg", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
+ }
+ else if (string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
+ }
+ else if (item.MediaType == DlnaProfileType.Video)
+ {
+ // Default to AVI for video
+ contentFeatures = "DLNA.ORG_PN=AVI";
+ }
+ else
+ {
+ // Default to MP3 for audio
+ contentFeatures = "DLNA.ORG_PN=MP3";
+ }
+
+ return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+ }
+
+ private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaStream> mediaStreams, DeviceProfile profile)
{
var video = item as Video;
if (video != null)
{
- return new PlaylistItemFactory(_itemRepository).Create(video, profile);
+ return new PlaylistItemFactory().Create(video, mediaStreams, profile);
}
var audio = item as Audio;
if (audio != null)
{
- return new PlaylistItemFactory(_itemRepository).Create(audio, profile);
+ return new PlaylistItemFactory().Create(audio, mediaStreams, profile);
}
var photo = item as Photo;
if (photo != null)
{
- return new PlaylistItemFactory(_itemRepository).Create(photo, profile);
+ return new PlaylistItemFactory().Create(photo, profile);
}
throw new ArgumentException("Unrecognized item type.");
@@ -482,11 +549,18 @@ namespace MediaBrowser.Dlna.PlayTo
await _device.SetStop();
return true;
}
+
nextTrack.PlayState = 1;
- _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, nextTrack.DlnaHeaders);
- await _device.SetAvTransport(nextTrack.StreamUrl, nextTrack.DlnaHeaders, nextTrack.Didl);
+
+ var dlnaheaders = GetDlnaHeaders(nextTrack);
+
+ _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, dlnaheaders);
+
+ await _device.SetAvTransport(nextTrack.StreamUrl, dlnaheaders, nextTrack.Didl);
+
if (nextTrack.StartPositionTicks > 0 && !nextTrack.Transcode)
await _device.Seek(TimeSpan.FromTicks(nextTrack.StartPositionTicks));
+
return true;
}
@@ -508,7 +582,7 @@ namespace MediaBrowser.Dlna.PlayTo
return Task.FromResult(false);
prevTrack.PlayState = 1;
- return _device.SetAvTransport(prevTrack.StreamUrl, prevTrack.DlnaHeaders, prevTrack.Didl);
+ return _device.SetAvTransport(prevTrack.StreamUrl, GetDlnaHeaders(prevTrack), prevTrack.Didl);
}
#endregion
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
index d02da303b..ca76116fe 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Linq;
@@ -16,7 +17,6 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Session;
namespace MediaBrowser.Dlna.PlayTo
{
@@ -54,10 +54,8 @@ namespace MediaBrowser.Dlna.PlayTo
_config = config;
}
- public async void Start()
+ public void Start()
{
- _logger.Log(LogSeverity.Info, "PlayTo-Manager starting");
-
_locations = new ConcurrentDictionary<string, DateTime>();
foreach (var network in NetworkInterface.GetAllNetworkInterfaces())
@@ -73,7 +71,7 @@ namespace MediaBrowser.Dlna.PlayTo
IPAddress localIp = null;
- foreach (UnicastIPAddressInformation ipInfo in network.GetIPProperties().UnicastAddresses)
+ foreach (var ipInfo in network.GetIPProperties().UnicastAddresses)
{
if (ipInfo.Address.AddressFamily == AddressFamily.InterNetwork)
{
@@ -95,8 +93,6 @@ namespace MediaBrowser.Dlna.PlayTo
{
_logger.ErrorException("Failed to Initilize Socket", e);
}
-
- await Task.Delay(100).ConfigureAwait(false);
}
}
@@ -139,7 +135,7 @@ namespace MediaBrowser.Dlna.PlayTo
_logger.Info("SSDP listener - Task completed");
}
- catch (OperationCanceledException c)
+ catch (OperationCanceledException)
{
}
catch (Exception e)
@@ -158,7 +154,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
await CreateController(uri).ConfigureAwait(false);
}
- catch (OperationCanceledException c)
+ catch (OperationCanceledException)
{
}
catch (Exception ex)
@@ -180,10 +176,12 @@ namespace MediaBrowser.Dlna.PlayTo
{
socket.SendTo(request, new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900));
- await Task.Delay(10000).ConfigureAwait(false);
+ var delay = _config.Configuration.DlnaOptions.ClientDiscoveryIntervalSeconds * 1000;
+
+ await Task.Delay(delay).ConfigureAwait(false);
}
}
- catch (OperationCanceledException c)
+ catch (OperationCanceledException)
{
}
catch (Exception ex)
diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs
index 1304f61b1..3992fbfbf 100644
--- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Dlna;
+using System.Collections.Generic;
namespace MediaBrowser.Dlna.PlayTo
{
@@ -14,16 +15,29 @@ namespace MediaBrowser.Dlna.PlayTo
public string Container { get; set; }
- public string MimeType { get; set; }
-
public int PlayState { get; set; }
public string StreamUrl { get; set; }
- public string DlnaHeaders { get; set; }
-
public string Didl { get; set; }
public long StartPositionTicks { get; set; }
+
+ public string VideoCodec { get; set; }
+
+ public string AudioCodec { get; set; }
+
+ public List<TranscodingSetting> TranscodingSettings { get; set; }
+
+ public int? AudioStreamIndex { get; set; }
+
+ public int? SubtitleStreamIndex { get; set; }
+
+ public string DeviceProfileName { get; set; }
+
+ public PlaylistItem()
+ {
+ TranscodingSettings = new List<TranscodingSetting>();
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
index 6817c4eaa..e4c49a224 100644
--- a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
@@ -1,9 +1,9 @@
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -12,15 +12,9 @@ namespace MediaBrowser.Dlna.PlayTo
{
public class PlaylistItemFactory
{
- private readonly IItemRepository _itemRepo;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public PlaylistItemFactory(IItemRepository itemRepo)
- {
- _itemRepo = itemRepo;
- }
-
- public PlaylistItem Create(Audio item, DeviceProfile profile)
+ public PlaylistItem Create(Audio item, List<MediaStream> mediaStreams, DeviceProfile profile)
{
var playlistItem = new PlaylistItem
{
@@ -28,23 +22,21 @@ namespace MediaBrowser.Dlna.PlayTo
MediaType = DlnaProfileType.Audio
};
- var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
- {
- ItemId = item.Id,
- Type = MediaStreamType.Audio
- });
-
var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
- var directPlay = profile.DirectPlayProfiles
- .FirstOrDefault(i => i.Type == playlistItem.MediaType && IsSupported(i, item, audioStream));
-
- if (directPlay != null)
+ if (profile.CodecProfiles.Where(i => i.Type == CodecType.AudioCodec)
+ .All(i => IsCodecProfileSupported(i, item.Path, null, audioStream)))
{
- playlistItem.Transcode = false;
- playlistItem.Container = Path.GetExtension(item.Path);
+ var directPlay = profile.DirectPlayProfiles
+ .FirstOrDefault(i => i.Type == playlistItem.MediaType && IsSupported(i, item, audioStream));
- return playlistItem;
+ if (directPlay != null)
+ {
+ playlistItem.Transcode = false;
+ playlistItem.Container = Path.GetExtension(item.Path);
+
+ return playlistItem;
+ }
}
var transcodingProfile = profile.TranscodingProfiles
@@ -53,11 +45,10 @@ namespace MediaBrowser.Dlna.PlayTo
if (transcodingProfile != null)
{
playlistItem.Transcode = true;
-
+ playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList();
playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.');
+ playlistItem.AudioCodec = transcodingProfile.AudioCodec;
}
-
- AttachMediaProfile(playlistItem, profile);
return playlistItem;
}
@@ -87,16 +78,14 @@ namespace MediaBrowser.Dlna.PlayTo
if (transcodingProfile != null)
{
playlistItem.Transcode = true;
-
+ playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList();
playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.');
}
-
- AttachMediaProfile(playlistItem, profile);
return playlistItem;
}
- public PlaylistItem Create(Video item, DeviceProfile profile)
+ public PlaylistItem Create(Video item, List<MediaStream> mediaStreams, DeviceProfile profile)
{
var playlistItem = new PlaylistItem
{
@@ -104,24 +93,22 @@ namespace MediaBrowser.Dlna.PlayTo
MediaType = DlnaProfileType.Video
};
- var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
- {
- ItemId = item.Id
-
- }).ToList();
-
var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
- var directPlay = profile.DirectPlayProfiles
- .FirstOrDefault(i => i.Type == playlistItem.MediaType && IsSupported(i, item, videoStream, audioStream));
-
- if (directPlay != null)
+ if (profile.CodecProfiles.Where(i => i.Type == CodecType.VideoCodec || i.Type == CodecType.VideoAudioCodec)
+ .All(i => IsCodecProfileSupported(i, item.Path, videoStream, audioStream)))
{
- playlistItem.Transcode = false;
- playlistItem.Container = Path.GetExtension(item.Path);
+ var directPlay = profile.DirectPlayProfiles
+ .FirstOrDefault(i => i.Type == playlistItem.MediaType && IsSupported(i, item, videoStream, audioStream));
- return playlistItem;
+ if (directPlay != null)
+ {
+ playlistItem.Transcode = false;
+ playlistItem.Container = Path.GetExtension(item.Path);
+
+ return playlistItem;
+ }
}
var transcodingProfile = profile.TranscodingProfiles
@@ -130,63 +117,29 @@ namespace MediaBrowser.Dlna.PlayTo
if (transcodingProfile != null)
{
playlistItem.Transcode = true;
+ playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList();
playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.');
+ playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',').FirstOrDefault();
+ playlistItem.VideoCodec = transcodingProfile.VideoCodec;
}
- AttachMediaProfile(playlistItem, profile);
-
return playlistItem;
}
- private void AttachMediaProfile(PlaylistItem item, DeviceProfile profile)
- {
- var mediaProfile = GetMediaProfile(item, profile);
-
- if (mediaProfile != null)
- {
- item.MimeType = (mediaProfile.MimeType ?? string.Empty).Split('/').LastOrDefault();
-
- // TODO: Org_pn?
- }
- }
-
- private MediaProfile GetMediaProfile(PlaylistItem item, DeviceProfile profile)
- {
- return profile.MediaProfiles.FirstOrDefault(i =>
- {
- if (i.Type == item.MediaType)
- {
- if (string.Equals(item.Container.TrimStart('.'), i.Container.TrimStart('.'), StringComparison.OrdinalIgnoreCase))
- {
- // TODO: Enforce codecs
- return true;
- }
- }
-
- return false;
- });
- }
-
private bool IsSupported(DirectPlayProfile profile, Photo item)
{
var mediaPath = item.Path;
- if (profile.Containers.Length > 0)
+ if (profile.Container.Length > 0)
{
// Check container type
var mediaContainer = Path.GetExtension(mediaPath);
- if (!profile.Containers.Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
+ if (!profile.GetContainers().Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
- // Check additional conditions
- if (!profile.Conditions.Any(i => IsConditionSatisfied(i, mediaPath, null, null)))
- {
- return false;
- }
-
return true;
}
@@ -194,22 +147,16 @@ namespace MediaBrowser.Dlna.PlayTo
{
var mediaPath = item.Path;
- if (profile.Containers.Length > 0)
+ if (profile.Container.Length > 0)
{
// Check container type
var mediaContainer = Path.GetExtension(mediaPath);
- if (!profile.Containers.Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
+ if (!profile.GetContainers().Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
- // Check additional conditions
- if (!profile.Conditions.Any(i => IsConditionSatisfied(i, mediaPath, null, audioStream)))
- {
- return false;
- }
-
return true;
}
@@ -222,11 +169,11 @@ namespace MediaBrowser.Dlna.PlayTo
var mediaPath = item.Path;
- if (profile.Containers.Length > 0)
+ if (profile.Container.Length > 0)
{
// Check container type
var mediaContainer = Path.GetExtension(mediaPath);
- if (!profile.Containers.Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
+ if (!profile.GetContainers().Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
@@ -254,12 +201,6 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
- // Check additional conditions
- if (!profile.Conditions.Any(i => IsConditionSatisfied(i, mediaPath, videoStream, audioStream)))
- {
- return false;
- }
-
return true;
}
@@ -281,6 +222,24 @@ namespace MediaBrowser.Dlna.PlayTo
return true;
}
+ private bool IsCodecProfileSupported(CodecProfile profile, string mediaPath, MediaStream videoStream, MediaStream audioStream)
+ {
+ var codecs = profile.GetCodecs();
+ var stream = profile.Type == CodecType.VideoCodec ? videoStream : audioStream;
+ var existingCodec = (stream == null ? null : stream.Codec) ?? string.Empty;
+
+ if (codecs.Count == 0 || codecs.Contains(existingCodec, StringComparer.OrdinalIgnoreCase))
+ {
+ // Check additional conditions
+ if (!profile.Conditions.Any(i => IsConditionSatisfied(i, mediaPath, videoStream, audioStream)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
/// <summary>
/// Determines whether [is condition satisfied] [the specified condition].
/// </summary>
@@ -292,30 +251,75 @@ namespace MediaBrowser.Dlna.PlayTo
/// <exception cref="System.InvalidOperationException">Unexpected ProfileConditionType</exception>
private bool IsConditionSatisfied(ProfileCondition condition, string mediaPath, MediaStream videoStream, MediaStream audioStream)
{
- var actualValue = GetConditionValue(condition, mediaPath, videoStream, audioStream);
+ if (condition.Property == ProfileConditionValue.Has64BitOffsets)
+ {
+ // TODO: Determine how to evaluate this
+ }
- if (actualValue.HasValue)
+ if (condition.Property == ProfileConditionValue.VideoProfile)
{
- long expected;
- if (long.TryParse(condition.Value, NumberStyles.Any, _usCulture, out expected))
+ var profile = videoStream == null ? null : videoStream.Profile;
+
+ if (!string.IsNullOrWhiteSpace(profile))
{
switch (condition.Condition)
{
case ProfileConditionType.Equals:
- return actualValue.Value == expected;
- case ProfileConditionType.GreaterThanEqual:
- return actualValue.Value >= expected;
- case ProfileConditionType.LessThanEqual:
- return actualValue.Value <= expected;
+ return string.Equals(profile, condition.Value, StringComparison.OrdinalIgnoreCase);
case ProfileConditionType.NotEquals:
- return actualValue.Value != expected;
+ return !string.Equals(profile, condition.Value, StringComparison.OrdinalIgnoreCase);
default:
throw new InvalidOperationException("Unexpected ProfileConditionType");
}
}
}
- return false;
+ else if (condition.Property == ProfileConditionValue.AudioProfile)
+ {
+ var profile = audioStream == null ? null : audioStream.Profile;
+
+ if (!string.IsNullOrWhiteSpace(profile))
+ {
+ switch (condition.Condition)
+ {
+ case ProfileConditionType.Equals:
+ return string.Equals(profile, condition.Value, StringComparison.OrdinalIgnoreCase);
+ case ProfileConditionType.NotEquals:
+ return !string.Equals(profile, condition.Value, StringComparison.OrdinalIgnoreCase);
+ default:
+ throw new InvalidOperationException("Unexpected ProfileConditionType");
+ }
+ }
+ }
+
+ else
+ {
+ var actualValue = GetConditionValue(condition, mediaPath, videoStream, audioStream);
+
+ if (actualValue.HasValue)
+ {
+ long expected;
+ if (long.TryParse(condition.Value, NumberStyles.Any, _usCulture, out expected))
+ {
+ switch (condition.Condition)
+ {
+ case ProfileConditionType.Equals:
+ return actualValue.Value == expected;
+ case ProfileConditionType.GreaterThanEqual:
+ return actualValue.Value >= expected;
+ case ProfileConditionType.LessThanEqual:
+ return actualValue.Value <= expected;
+ case ProfileConditionType.NotEquals:
+ return actualValue.Value != expected;
+ default:
+ throw new InvalidOperationException("Unexpected ProfileConditionType");
+ }
+ }
+ }
+ }
+
+ // Value doesn't exist in metadata. Fail it if required.
+ return !condition.IsRequired;
}
/// <summary>
@@ -347,6 +351,12 @@ 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");
}
diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
index 7a4928e5c..f540a8004 100644
--- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
+++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
@@ -49,7 +49,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url.ToString(),
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging
+ LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
};
options.RequestHeaders["HOST"] = ip + ":" + port;
@@ -88,7 +88,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url.ToString(),
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging
+ LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
};
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
@@ -112,7 +112,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url.ToString(),
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging
+ LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
};
options.RequestHeaders["SOAPAction"] = soapAction;
diff --git a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs
index cb2b72a03..6cd66c16a 100644
--- a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs
+++ b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs
@@ -1,6 +1,5 @@
-using MediaBrowser.Model.Dto;
+using MediaBrowser.Controller.Dlna;
using MediaBrowser.Model.Entities;
-using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -10,90 +9,20 @@ namespace MediaBrowser.Dlna.PlayTo
class StreamHelper
{
/// <summary>
- /// Gets the dlna headers.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns></returns>
- internal static string GetDlnaHeaders(PlaylistItem item)
- {
- var orgOp = item.Transcode ? ";DLNA.ORG_OP=00" : ";DLNA.ORG_OP=01";
-
- var orgCi = item.Transcode ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
-
- const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
-
- var contentFeatures = string.Empty;
-
- if (string.Equals(item.Container, "mp3", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=MP3";
- }
- else if (string.Equals(item.Container, "wma", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=WMABASE";
- }
- else if (string.Equals(item.Container, "wmw", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
- }
- else if (string.Equals(item.Container, "asf", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=WMVMED_BASE";
- }
- else if (string.Equals(item.Container, "avi", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=AVI";
- }
- else if (string.Equals(item.Container, "mkv", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=MATROSKA";
- }
- else if (string.Equals(item.Container, "mp4", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
- }
- else if (string.Equals(item.Container, "mpeg", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
- }
- else if (string.Equals(item.Container, "ts", StringComparison.OrdinalIgnoreCase))
- {
- contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
- }
- else if (item.MediaType == Controller.Dlna.DlnaProfileType.Video)
- {
- //Default to AVI for video
- contentFeatures = "DLNA.ORG_PN=AVI";
- }
- else
- {
- //Default to MP3 for audio
- contentFeatures = "DLNA.ORG_PN=MP3";
- }
-
- return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
- }
-
- #region Audio
-
- /// <summary>
/// Gets the audio URL.
/// </summary>
+ /// <param name="deviceProperties">The device properties.</param>
/// <param name="item">The item.</param>
+ /// <param name="streams">The streams.</param>
/// <param name="serverAddress">The server address.</param>
/// <returns>System.String.</returns>
- internal static string GetAudioUrl(PlaylistItem item, string serverAddress)
+ internal static string GetAudioUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress)
{
- if (!item.Transcode)
- return string.Format("{0}/audio/{1}/stream{2}?Static=True", serverAddress, item.ItemId, item.Container);
+ var dlnaCommand = BuildDlnaUrl(item.DeviceProfileName, item.MediaSourceId, deviceProperties.UUID, !item.Transcode, null, item.AudioCodec, item.AudioStreamIndex, item.SubtitleStreamIndex, null, 128000, item.StartPositionTicks, item.TranscodingSettings);
- return string.Format("{0}/audio/{1}/stream.mp3?AudioCodec=Mp3", serverAddress, item.ItemId);
+ return string.Format("{0}/audio/{1}/stream{2}?{3}", serverAddress, item.ItemId, "." + item.Container.TrimStart('.'), dlnaCommand);
}
- #endregion
-
- #region Video
-
/// <summary>
/// Gets the video URL.
/// </summary>
@@ -104,97 +33,41 @@ namespace MediaBrowser.Dlna.PlayTo
/// <returns>The url to send to the device</returns>
internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress)
{
- string dlnaCommand = string.Empty;
- if (!item.Transcode)
- {
- dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, null, null, null, null, null, null, null, null, null, null, item.MimeType);
- return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.Container, dlnaCommand);
- }
- var videostream = streams.Where(m => m.Type == MediaStreamType.Video).OrderBy(m => m.IsDefault).FirstOrDefault();
- var audiostream = streams.Where(m => m.Type == MediaStreamType.Audio).OrderBy(m => m.IsDefault).FirstOrDefault();
-
- var videoCodec = GetVideoCodec(videostream);
- var audioCodec = GetAudioCodec(audiostream);
- int? videoBitrate = null;
- int? audioBitrate = null;
- int? audioChannels = null;
-
- if (videoCodec != VideoCodecs.Copy)
- videoBitrate = 2000000;
+ var dlnaCommand = BuildDlnaUrl(item.DeviceProfileName, item.MediaSourceId, deviceProperties.UUID, !item.Transcode, item.VideoCodec, item.AudioCodec, item.AudioStreamIndex, item.SubtitleStreamIndex, 1500000, 128000, item.StartPositionTicks, item.TranscodingSettings);
- if (audioCodec != AudioCodecs.Copy)
- {
- audioBitrate = 128000;
- audioChannels = 2;
- }
-
- dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, videoCodec, audioCodec, null, null, videoBitrate, audioChannels, audioBitrate, item.StartPositionTicks, "baseline", "3", item.MimeType);
return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.Container, dlnaCommand);
}
/// <summary>
- /// Gets the video codec.
- /// </summary>
- /// <param name="videoStream">The video stream.</param>
- /// <returns></returns>
- private static VideoCodecs GetVideoCodec(MediaStream videoStream)
- {
- switch (videoStream.Codec.ToLower())
- {
- case "h264":
- case "mpeg4":
- return VideoCodecs.Copy;
-
- }
- return VideoCodecs.H264;
- }
-
- /// <summary>
- /// Gets the audio codec.
- /// </summary>
- /// <param name="audioStream">The audio stream.</param>
- /// <returns></returns>
- private static AudioCodecs GetAudioCodec(MediaStream audioStream)
- {
- if (audioStream != null)
- {
- switch (audioStream.Codec.ToLower())
- {
- case "aac":
- case "mp3":
- case "wma":
- return AudioCodecs.Copy;
-
- }
- }
- return AudioCodecs.Aac;
- }
-
- /// <summary>
/// Builds the dlna URL.
/// </summary>
- private static string BuildDlnaUrl(string deviceID, bool isStatic, VideoCodecs? videoCodec, AudioCodecs? audioCodec, int? subtitleIndex, int? audiostreamIndex, int? videoBitrate, int? audiochannels, int? audioBitrate, long? startPositionTicks, string profile, string videoLevel, string mimeType)
+ private static string BuildDlnaUrl(string deviceProfileName, string mediaSourceId, string deviceID, bool isStatic, string videoCodec, string audioCodec, int? audiostreamIndex, int? subtitleIndex, int? videoBitrate, int? audioBitrate, long? startPositionTicks, List<TranscodingSetting> settings)
{
- var usCulture = new CultureInfo("en-US");
+ var profile = settings.Where(i => i.Name == TranscodingSettingType.VideoProfile).Select(i => i.Value).FirstOrDefault();
+ var videoLevel = settings.Where(i => i.Name == TranscodingSettingType.VideoLevel).Select(i => i.Value).FirstOrDefault();
+ var maxAudioChannels = settings.Where(i => i.Name == TranscodingSettingType.MaxAudioChannels).Select(i => i.Value).FirstOrDefault();
- var dlnaparam = string.Format("Params={0};", deviceID);
- dlnaparam += isStatic ? "true;" : "false;";
- dlnaparam += videoCodec.HasValue ? videoCodec.Value + ";" : ";";
- dlnaparam += audioCodec.HasValue ? audioCodec.Value + ";" : ";";
- dlnaparam += audiostreamIndex.HasValue ? audiostreamIndex.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += subtitleIndex.HasValue ? subtitleIndex.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += videoBitrate.HasValue ? videoBitrate.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += audioBitrate.HasValue ? audioBitrate.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += audiochannels.HasValue ? audiochannels.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += startPositionTicks.HasValue ? startPositionTicks.Value.ToString(usCulture) + ";" : ";";
- dlnaparam += profile + ";";
- dlnaparam += videoLevel + ";";
- dlnaparam += mimeType + ";";
+ var usCulture = new CultureInfo("en-US");
- return dlnaparam;
+ var list = new List<string>
+ {
+ deviceProfileName ?? string.Empty,
+ deviceID ?? string.Empty,
+ mediaSourceId ?? string.Empty,
+ isStatic.ToString().ToLower(),
+ videoCodec ?? string.Empty,
+ audioCodec ?? string.Empty,
+ audiostreamIndex.HasValue ? audiostreamIndex.Value.ToString(usCulture) : string.Empty,
+ subtitleIndex.HasValue ? subtitleIndex.Value.ToString(usCulture) : string.Empty,
+ videoBitrate.HasValue ? videoBitrate.Value.ToString(usCulture) : string.Empty,
+ audioBitrate.HasValue ? audioBitrate.Value.ToString(usCulture) : string.Empty,
+ maxAudioChannels ?? string.Empty,
+ startPositionTicks.HasValue ? startPositionTicks.Value.ToString(usCulture) : string.Empty,
+ profile ?? string.Empty,
+ videoLevel ?? string.Empty
+ };
+
+ return string.Format("Params={0}", string.Join(";", list.ToArray()));
}
-
- #endregion
-
}
} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
new file mode 100644
index 000000000..a1c661275
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
@@ -0,0 +1,59 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class DefaultProfile : DeviceProfile
+ {
+ public DefaultProfile()
+ {
+ ProtocolInfo = "DLNA";
+
+ ClientType = "DLNA";
+ Manufacturer = "Media Browser";
+ ModelDescription = "Media Browser";
+ ModelName = "Media Browser";
+ ModelNumber = "Media Browser";
+ ModelUrl = "http://mediabrowser3.com/";
+ ManufacturerUrl = "http://mediabrowser3.com/";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new TranscodingProfile
+ {
+ Container = "ts",
+ Type = DlnaProfileType.Video,
+ AudioCodec = "aac",
+ VideoCodec = "h264",
+
+ Settings = new []
+ {
+ new TranscodingSetting {Name = TranscodingSettingType.VideoLevel, Value = "3"},
+ new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"}
+ }
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mp3,wma",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "avi,mp4",
+ Type = DlnaProfileType.Video
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
new file mode 100644
index 000000000..cca6ab6bb
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
@@ -0,0 +1,27 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class DenonAvrProfile : DefaultProfile
+ {
+ public DenonAvrProfile()
+ {
+ Name = "Denon AVR";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"Denon:\[AVR:.*",
+ Manufacturer = "Denon"
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mp3,flac,m4a,wma",
+ Type = DlnaProfileType.Audio
+ },
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/LgTvProfile.cs b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs
new file mode 100644
index 000000000..ec20c9df8
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs
@@ -0,0 +1,192 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class LgTvProfile : DefaultProfile
+ {
+ public LgTvProfile()
+ {
+ Name = "LG Smart TV";
+
+ TimelineOffsetSeconds = 10;
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"LG.*",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "User-Agent",
+ Value = "LG",
+ Match = HeaderMatchType.Substring
+ }
+ }
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ AudioCodec = "ac3",
+ VideoCodec = "h264",
+ Type = DlnaProfileType.Video
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "aac,ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ VideoCodec = "h264",
+ AudioCodec = "aac,ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "aac,ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg4",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3,aac,mp3",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
new file mode 100644
index 000000000..e7086c205
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
@@ -0,0 +1,33 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class LinksysDMA2100Profile : DefaultProfile
+ {
+ public LinksysDMA2100Profile()
+ {
+ // Linksys DMA2100us does not need any transcoding of the formats we support statically
+ Name = "Linksys DMA2100";
+
+ Identification = new DeviceIdentification
+ {
+ ModelName = "DMA2100us"
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mp3,flac,m4a,wma",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "avi,mp4,mkv,ts",
+ Type = DlnaProfileType.Video
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
new file mode 100644
index 000000000..6755c0680
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
@@ -0,0 +1,186 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class PanasonicVieraProfile : DefaultProfile
+ {
+ public PanasonicVieraProfile()
+ {
+ Name = "Panasonic Viera";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"VIERA",
+ Manufacturer = "Panasonic",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "User-Agent",
+ Value = "Panasonic MIL DLNA",
+ Match = HeaderMatchType.Substring
+ }
+ }
+ };
+
+ TimelineOffsetSeconds = 10;
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ AudioCodec = "ac3",
+ VideoCodec = "h264",
+ Type = DlnaProfileType.Video
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video,mpeg4",
+ AudioCodec = "ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ VideoCodec = "h264",
+ AudioCodec = "aac,ac3,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "aac,mp3",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264",
+ AudioCodec = "aac,ac3,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mov",
+ VideoCodec = "h264",
+ AudioCodec = "aac,pcm",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mpeg4",
+ AudioCodec = "pcm",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "flv",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitDepth,
+ Value = "8",
+ IsRequired = false
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
new file mode 100644
index 000000000..fa6b1201a
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
@@ -0,0 +1,315 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SamsungSmartTvProfile : DefaultProfile
+ {
+ public SamsungSmartTvProfile()
+ {
+ Name = "Samsung Smart TV";
+
+ SupportsAlbumArtInDidl = true;
+
+ Identification = new DeviceIdentification
+ {
+ ModelUrl = "samsung.com"
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ AudioCodec = "ac3",
+ VideoCodec = "h264",
+ Type = DlnaProfileType.Video
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "h264,mpeg4,mjpeg",
+ AudioCodec = "mp3,ac3,wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "h264,mpeg4,mjpeg",
+ AudioCodec = "mp3,ac3,dca",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ VideoCodec = "h264,mpeg4,mjpeg4",
+ AudioCodec = "mp3,ac3,dca,aac",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "mp3,aac",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "3gpp",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "aac,he-aac",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpg,mpeg",
+ VideoCodec = "mpeg1video,mpeg2video,h264",
+ AudioCodec = "ac3,mp2,mp3,aac",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "vro,vob",
+ VideoCodec = "mpeg1video,mpeg2video",
+ AudioCodec = "ac3,mp2,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg2video,h264,vc1",
+ AudioCodec = "ac3,aac,mp3,eac3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2,wmv3",
+ AudioCodec = "wmav2,wmavoice",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg2video",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "30720000"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg4",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "8192000"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "37500000"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "wmv2,wmv3,vc1",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "25600000"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3,wmav2,dca,aac,mp3",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6"
+ }
+ }
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "mkv",
+ MimeType = "video/x-mkv",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
new file mode 100644
index 000000000..49aa47027
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
@@ -0,0 +1,180 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBlurayPlayer2013Profile : DefaultProfile
+ {
+ public SonyBlurayPlayer2013Profile()
+ {
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"Blu-ray Disc Player",
+ Manufacturer = "Sony",
+ ModelNumber = "BDP-2013"
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ Manufacturer = "Microsoft Corporation";
+
+ ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3",
+ Type = DlnaProfileType.Video
+ },
+
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg1video,mpeg2video,h264",
+ AudioCodec = "ac3,aac,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg1video,mpeg2video",
+ AudioCodec = "ac3,mp3,mp2,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "mpeg4,h264",
+ AudioCodec = "ac3,aac,pcm,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mpeg4,h264",
+ AudioCodec = "ac3,aac,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ VideoCodec = "mpeg4,h264",
+ AudioCodec = "ac3,dca,aac,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6",
+ IsRequired = false
+ }
+ }
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs
new file mode 100644
index 000000000..512172670
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs
@@ -0,0 +1,261 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBlurayPlayerProfile : DefaultProfile
+ {
+ public SonyBlurayPlayerProfile()
+ {
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"Blu-ray Disc Player",
+ Manufacturer = "Sony",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @"(Blu-ray Disc Player|Home Theater System|Home Theatre System|Media Player)",
+ Match = HeaderMatchType.Regex
+ },
+
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Physical-Unit-Info",
+ Value = @"(Blu-ray Disc Player|Home Theater System|Home Theatre System|Media Player)",
+ Match = HeaderMatchType.Regex
+ }
+ }
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ Manufacturer = "Microsoft Corporation";
+
+ ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "ac3",
+ Type = DlnaProfileType.Video
+ },
+
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg1video,mpeg2video,h264",
+ AudioCodec = "ac3,aac,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg1video,mpeg2video",
+ AudioCodec = "ac3,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi,mp4",
+ VideoCodec = "mpeg4,h264",
+ AudioCodec = "ac3,aac,mp3,pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "15360000",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2",
+ IsRequired = false
+ }
+ }
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264,mpeg4,vc1",
+ AudioCodec = "ac3,aac,mp3",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "avi",
+ MimeType = "video/mpeg",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mkv",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mp4",
+ MimeType = "video/mpeg",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mpeg",
+ MimeType = "video/mpeg",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mp3",
+ MimeType = "audio/mpeg",
+ Type = DlnaProfileType.Audio
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs
new file mode 100644
index 000000000..042cc0a96
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs
@@ -0,0 +1,286 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBravia2010Profile : DefaultProfile
+ {
+ public SonyBravia2010Profile()
+ {
+ Name = "Sony Bravia (2010)";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"KDL-\d{2}[EHLNPB]X\d[01]\d.*",
+ Manufacturer = "Sony",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @".*KDL-\d{2}[EHLNPB]X\d[01]\d.*",
+ Match = HeaderMatchType.Regex
+ }
+ }
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ ModelUrl = "http://www.microsoft.com/";
+ Manufacturer = "Microsoft Corporation";
+ ManufacturerUrl = "http://www.microsoft.com/";
+ SonyAggregationFlags = "10";
+ 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";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac",
+ Type = DlnaProfileType.Video,
+ EnableMpegtsM2TsMode = true
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg1video,mpeg2video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video,mpeg1video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ AudioCodec="ac3,aac,mp3",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="mpeg2video",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mpeg",
+ VideoCodec="mpeg1video,mpeg2video",
+ MimeType = "video/mpeg",
+ OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "20000000"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg2video",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "20000000"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.NotEquals,
+ Property = ProfileConditionValue.AudioProfile,
+ Value = "he-aac"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs
new file mode 100644
index 000000000..401c40c36
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs
@@ -0,0 +1,304 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBravia2011Profile : DefaultProfile
+ {
+ public SonyBravia2011Profile()
+ {
+ Name = "Sony Bravia (2011)";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"KDL-\d{2}([A-Z]X\d2\d|CX400).*",
+ Manufacturer = "Sony",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @".*KDL-\d{2}([A-Z]X\d2\d|CX400).*",
+ Match = HeaderMatchType.Regex
+ }
+ }
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ ModelUrl = "http://www.microsoft.com/";
+ Manufacturer = "Microsoft Corporation";
+ ManufacturerUrl = "http://www.microsoft.com/";
+ SonyAggregationFlags = "10";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac",
+ Type = DlnaProfileType.Video,
+ EnableMpegtsM2TsMode = true
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "ac3,aac,mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video,mpeg1video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2,wmv3,vc1",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ AudioCodec="ac3,aac,mp3",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="mpeg2video",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mpeg",
+ VideoCodec="mpeg1video,mpeg2video",
+ MimeType = "video/mpeg",
+ OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "20000000"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg2video",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "20000000"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.NotEquals,
+ Property = ProfileConditionValue.AudioProfile,
+ Value = "he-aac"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs
new file mode 100644
index 000000000..2d24c406e
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs
@@ -0,0 +1,246 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBravia2012Profile : DefaultProfile
+ {
+ public SonyBravia2012Profile()
+ {
+ Name = "Sony Bravia (2012)";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"KDL-\d{2}[A-Z]X\d5(\d|G).*",
+ Manufacturer = "Sony",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @".*KDL-\d{2}[A-Z]X\d5(\d|G).*",
+ Match = HeaderMatchType.Regex
+ }
+ }
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ ModelUrl = "http://www.microsoft.com/";
+ Manufacturer = "Microsoft Corporation";
+ ManufacturerUrl = "http://www.microsoft.com/";
+ SonyAggregationFlags = "10";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac",
+ Type = DlnaProfileType.Video,
+ EnableMpegtsM2TsMode = true
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "ac3,aac,mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mpeg4",
+ AudioCodec = "ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video,mpeg1video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2,wmv3,vc1",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ AudioCodec="ac3,aac,mp3",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="mpeg2video",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mpeg",
+ VideoCodec="mpeg1video,mpeg2video",
+ MimeType = "video/mpeg",
+ OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs
new file mode 100644
index 000000000..10f712958
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs
@@ -0,0 +1,264 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyBravia2013Profile : DefaultProfile
+ {
+ public SonyBravia2013Profile()
+ {
+ Name = "Sony Bravia (2013)";
+
+ Identification = new DeviceIdentification
+ {
+ FriendlyName = @"KDL-\d{2}[WR][5689]\d{2}A.*",
+ Manufacturer = "Sony",
+
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @".*KDL-\d{2}[WR][5689]\d{2}A.*",
+ Match = HeaderMatchType.Regex
+ }
+ }
+ };
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "3.0";
+ ModelUrl = "http://www.microsoft.com/";
+ Manufacturer = "Microsoft Corporation";
+ ManufacturerUrl = "http://www.microsoft.com/";
+ SonyAggregationFlags = "10";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,aac",
+ Type = DlnaProfileType.Video,
+ EnableMpegtsM2TsMode = true
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "ac3,eac3,aac,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "ac3,eac3,aac,mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mov",
+ VideoCodec = "h264,mpeg4,mjpeg",
+ AudioCodec = "ac3,eac3,aac,mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ VideoCodec = "h264,mpeg4,vp8",
+ AudioCodec = "ac3,eac3,aac,mp3,mp2,pcm,vorbis",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mpeg4",
+ AudioCodec = "ac3,eac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mjpeg",
+ AudioCodec = "pcm",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video,mpeg1video",
+ AudioCodec = "mp3,mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2,wmv3,vc1",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "wav",
+ AudioCodec = "pcm",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ 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"}
+ }
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="h264",
+ AudioCodec="ac3,aac,mp3",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "ts",
+ VideoCodec="mpeg2video",
+ MimeType = "video/vnd.dlna.mpeg-tts",
+ OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "mpeg",
+ VideoCodec="mpeg1video,mpeg2video",
+ MimeType = "video/mpeg",
+ OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
new file mode 100644
index 000000000..e5fc1ed07
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
@@ -0,0 +1,233 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class SonyPs3Profile : DefaultProfile
+ {
+ public SonyPs3Profile()
+ {
+ Name = "Sony Bravia (2010)";
+
+ Identification = new DeviceIdentification
+ {
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Name = "User-Agent",
+ Value = @"PLAYSTATION 3",
+ Match = HeaderMatchType.Substring
+ },
+
+ new HttpHeaderInfo
+ {
+ Name = "X-AV-Client-Info",
+ Value = @"PLAYSTATION 3",
+ Match = HeaderMatchType.Substring
+ }
+ }
+ };
+
+ SonyAggregationFlags = "10";
+ XDlnaDoc = "DMS-1.50";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Video
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "15360000",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6",
+ IsRequired = false
+ },
+
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioBitrate,
+ Value = "640000",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "wmapro",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.NotEquals,
+ Property = ProfileConditionValue.AudioProfile,
+ Value = "he-aac",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.NotEquals,
+ Property = ProfileConditionValue.AudioProfile,
+ Value = "he-aac"
+ }
+ }
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "mp4,mov",
+ AudioCodec="aac",
+ MimeType = "video/mp4",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "avi",
+ MimeType = "video/divx",
+ OrgPn="AVI",
+ Type = DlnaProfileType.Video
+ },
+
+ new MediaProfile
+ {
+ Container = "wav",
+ MimeType = "audio/wav",
+ Type = DlnaProfileType.Audio
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
new file mode 100644
index 000000000..52d4a5f29
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
@@ -0,0 +1,241 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class WdtvLiveProfile : DefaultProfile
+ {
+ public WdtvLiveProfile()
+ {
+ Name = "WDTV Live";
+
+ TimelineOffsetSeconds = 5;
+ IgnoreTranscodeByteRangeRequests = true;
+
+ Identification = new DeviceIdentification
+ {
+ ModelName = "WD TV HD Live",
+
+ Headers = new []
+ {
+ new HttpHeaderInfo {Name = "User-Agent", Value = "alphanetworks", Match = HeaderMatchType.Substring},
+ new HttpHeaderInfo
+ {
+ Name = "User-Agent",
+ Value = "ALPHA Networks",
+ Match = HeaderMatchType.Substring
+ }
+ }
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ Type = DlnaProfileType.Audio,
+ AudioCodec = "mp3"
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+
+ Settings = new []
+ {
+ new TranscodingSetting {Name = TranscodingSettingType.VideoLevel, Value = "3"},
+ new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"}
+ }
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
+ AudioCodec = "ac3,dca,mp2,mp3,pcm"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "mpeg1video,mpeg2video",
+ AudioCodec = "ac3,dca,mp2,mp3,pcm"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mkv",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
+ AudioCodec = "ac3,dca,aac,mp2,mp3,pcm"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "ts",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "mpeg1video,mpeg2video,h264,vc1",
+ AudioCodec = "ac3,dca,mp2,mp3"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp4,mov",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "ac3,aac,mp2,mp3"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "vc1",
+ AudioCodec = "wmav2,wmapro"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ Type = DlnaProfileType.Video,
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp2,ac3"
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp2,mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ AudioCodec = "mp4",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "flac",
+ AudioCodec = "flac",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "ogg",
+ AudioCodec = "vorbis",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Container = "jpeg,png,gif,bmp,tiff"
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "ts",
+ OrgPn = "MPEG_TS_SD_NA",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
new file mode 100644
index 000000000..7216457a3
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
@@ -0,0 +1,312 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class Xbox360Profile : DefaultProfile
+ {
+ public Xbox360Profile()
+ {
+ Name = "Xbox 360";
+
+ ModelName = "Windows Media Player Sharing";
+ ModelNumber = "12.0";
+ ModelUrl = "http://www.microsoft.com/";
+ Manufacturer = "Microsoft Corporation";
+ ManufacturerUrl = "http://www.microsoft.com/";
+ XDlnaDoc = "DMS-1.50";
+
+ TimelineOffsetSeconds = 40;
+ RequiresPlainFolders = true;
+ RequiresPlainVideoItems = true;
+
+ Identification = new DeviceIdentification
+ {
+ ModelName = "Xbox 360",
+
+ Headers = new []
+ {
+ new HttpHeaderInfo {Name = "User-Agent", Value = "Xbox", Match = HeaderMatchType.Substring},
+ new HttpHeaderInfo {Name = "User-Agent", Value = "Xenon", Match = HeaderMatchType.Substring}
+ }
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2",
+ AudioCodec = "wmav2",
+ Type = DlnaProfileType.Video,
+ TranscodeSeekInfo = TranscodeSeekInfo.Bytes,
+ EstimateContentLength = true,
+
+ Settings = new []
+ {
+ new TranscodingSetting {Name = TranscodingSettingType.MaxAudioChannels, Value = "6"},
+ new TranscodingSetting {Name = TranscodingSettingType.VideoLevel, Value = "3"},
+ new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"}
+ }
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "mpeg4",
+ AudioCodec = "ac3,mp3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "avi",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp4,mov",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "aac,ac3",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ VideoCodec = "wmv2,wmv3,vc1",
+ AudioCodec = "wmav2,wmapro",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "asf",
+ AudioCodec = "wmav2,wmapro,wmavoice",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "avi",
+ MimeType = "video/avi",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ ContainerProfiles = new[]
+ {
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Video,
+ Container = "mp4,mov",
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Has64BitOffsets,
+ Value = "false",
+ IsRequired = false
+ }
+ }
+ },
+
+ new ContainerProfile
+ {
+ Type = DlnaProfileType.Photo,
+
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ }
+ }
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "mpeg4",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1280"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "720"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "5120000",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "h264",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoLevel,
+ Value = "41",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "10240000",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoCodec,
+ Codec = "wmv2,wmv3,vc1",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "15360000",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "ac3,wmav2,wmapro",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6",
+ IsRequired = false
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudioCodec,
+ Codec = "aac",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "6",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.Equals,
+ Property = ProfileConditionValue.AudioProfile,
+ Value = "lc",
+ IsRequired = false
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs
new file mode 100644
index 000000000..0daa5d7a2
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs
@@ -0,0 +1,54 @@
+using MediaBrowser.Controller.Dlna;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ public class XboxOneProfile : DefaultProfile
+ {
+ public XboxOneProfile()
+ {
+ Name = "Xbox One";
+
+ Identification = new DeviceIdentification
+ {
+ ModelName = "Xbox One",
+ FriendlyName = "Xbox-SystemOS"
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mp3,wma",
+ Type = DlnaProfileType.Audio
+ }
+ };
+
+ MediaProfiles = new[]
+ {
+ new MediaProfile
+ {
+ Container = "avi",
+ MimeType = "video/x-msvideo",
+ Type = DlnaProfileType.Video
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs b/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs
new file mode 100644
index 000000000..f1af0af28
--- /dev/null
+++ b/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs
@@ -0,0 +1,115 @@
+using MediaBrowser.Common;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Logging;
+using System;
+
+namespace MediaBrowser.Dlna.Server
+{
+ public class DlnaServerEntryPoint : IServerEntryPoint
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly ILogger _logger;
+
+ private SsdpHandler _ssdpHandler;
+ private readonly IApplicationHost _appHost;
+
+ public DlnaServerEntryPoint(IServerConfigurationManager config, ILogManager logManager, IApplicationHost appHost)
+ {
+ _config = config;
+ _appHost = appHost;
+ _logger = logManager.GetLogger("DlnaServer");
+ }
+
+ public void Run()
+ {
+ _config.ConfigurationUpdated += ConfigurationUpdated;
+
+ //ReloadServer();
+ }
+
+ void ConfigurationUpdated(object sender, EventArgs e)
+ {
+ //ReloadServer();
+ }
+
+ private void ReloadServer()
+ {
+ var isStarted = _ssdpHandler != null;
+
+ if (_config.Configuration.DlnaOptions.EnableServer && !isStarted)
+ {
+ StartServer();
+ }
+ else if (!_config.Configuration.DlnaOptions.EnableServer && isStarted)
+ {
+ DisposeServer();
+ }
+ }
+
+ private readonly object _syncLock = new object();
+ private void StartServer()
+ {
+ var signature = GenerateServerSignature();
+
+ lock (_syncLock)
+ {
+ try
+ {
+ _ssdpHandler = new SsdpHandler(_logger, _config, signature);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error starting Dlna server", ex);
+ }
+ }
+ }
+
+ private void DisposeServer()
+ {
+ lock (_syncLock)
+ {
+ if (_ssdpHandler != null)
+ {
+ try
+ {
+ _ssdpHandler.Dispose();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing Dlna server", ex);
+ }
+ _ssdpHandler = null;
+ }
+ }
+ }
+
+ private string GenerateServerSignature()
+ {
+ var os = Environment.OSVersion;
+ var pstring = os.Platform.ToString();
+ switch (os.Platform)
+ {
+ case PlatformID.Win32NT:
+ case PlatformID.Win32S:
+ case PlatformID.Win32Windows:
+ pstring = "WIN";
+ break;
+ }
+
+ return String.Format(
+ "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 MediaBrowser/{4}",
+ pstring,
+ IntPtr.Size * 8,
+ os.Version.Major,
+ os.Version.Minor,
+ _appHost.ApplicationVersion
+ );
+ }
+
+ public void Dispose()
+ {
+ DisposeServer();
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Server/Headers.cs b/MediaBrowser.Dlna/Server/Headers.cs
new file mode 100644
index 000000000..859ae7fbf
--- /dev/null
+++ b/MediaBrowser.Dlna/Server/Headers.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace MediaBrowser.Dlna.Server
+{
+ public class Headers : IDictionary<string, string>
+ {
+ private readonly bool _asIs = false;
+ 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)
+ {
+ _asIs = asIs;
+ }
+
+ public Headers()
+ : this(asIs: false)
+ {
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _dict.Count;
+ }
+ }
+ public string HeaderBlock
+ {
+ get
+ {
+ var hb = new StringBuilder();
+ foreach (var h in this)
+ {
+ hb.AppendFormat("{0}: {1}\r\n", h.Key, h.Value);
+ }
+ return hb.ToString();
+ }
+ }
+ public Stream HeaderStream
+ {
+ get
+ {
+ return new MemoryStream(Encoding.ASCII.GetBytes(HeaderBlock));
+ }
+ }
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+ public ICollection<string> Keys
+ {
+ get
+ {
+ return _dict.Keys;
+ }
+ }
+ public ICollection<string> Values
+ {
+ get
+ {
+ return _dict.Values;
+ }
+ }
+
+
+ public string this[string key]
+ {
+ get
+ {
+ return _dict[Normalize(key)];
+ }
+ set
+ {
+ _dict[Normalize(key)] = value;
+ }
+ }
+
+
+ private string Normalize(string header)
+ {
+ if (!_asIs)
+ {
+ header = header.ToLower();
+ }
+ header = header.Trim();
+ if (!Validator.IsMatch(header))
+ {
+ throw new ArgumentException("Invalid header: " + header);
+ }
+ return header;
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return _dict.GetEnumerator();
+ }
+
+ public void Add(KeyValuePair<string, string> item)
+ {
+ Add(item.Key, item.Value);
+ }
+
+ public void Add(string key, string value)
+ {
+ _dict.Add(Normalize(key), value);
+ }
+
+ public void Clear()
+ {
+ _dict.Clear();
+ }
+
+ public bool Contains(KeyValuePair<string, string> item)
+ {
+ var p = new KeyValuePair<string, string>(Normalize(item.Key), item.Value);
+ return _dict.Contains(p);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _dict.ContainsKey(Normalize(key));
+ }
+
+ public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
+ {
+ return _dict.GetEnumerator();
+ }
+
+ public bool Remove(string key)
+ {
+ return _dict.Remove(Normalize(key));
+ }
+
+ public bool Remove(KeyValuePair<string, string> item)
+ {
+ return Remove(item.Key);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("({0})", string.Join(", ", (from x in _dict
+ select string.Format("{0}={1}", x.Key, x.Value))));
+ }
+
+ public bool TryGetValue(string key, out string value)
+ {
+ return _dict.TryGetValue(Normalize(key), out value);
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Server/RawHeaders.cs b/MediaBrowser.Dlna/Server/RawHeaders.cs
new file mode 100644
index 000000000..f57e6b9f3
--- /dev/null
+++ b/MediaBrowser.Dlna/Server/RawHeaders.cs
@@ -0,0 +1,16 @@
+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)
+ {
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Server/SsdpHandler.cs b/MediaBrowser.Dlna/Server/SsdpHandler.cs
new file mode 100644
index 000000000..63c2abbec
--- /dev/null
+++ b/MediaBrowser.Dlna/Server/SsdpHandler.cs
@@ -0,0 +1,260 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+
+namespace MediaBrowser.Dlna.Server
+{
+ public class SsdpHandler : IDisposable
+ {
+ private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
+ private readonly string _serverSignature;
+ private bool _isDisposed = false;
+
+ const string SSDPAddr = "239.255.255.250";
+ const int SSDPPort = 1900;
+
+ private readonly IPEndPoint _ssdpEndp = new IPEndPoint(IPAddress.Parse(SSDPAddr), SSDPPort);
+ private readonly IPAddress _ssdpIp = IPAddress.Parse(SSDPAddr);
+
+ private UdpClient _udpClient;
+
+ private readonly Dictionary<Guid, List<UpnpDevice>> _devices = new Dictionary<Guid, List<UpnpDevice>>();
+
+ public SsdpHandler(ILogger logger, IServerConfigurationManager config, string serverSignature)
+ {
+ _logger = logger;
+ _config = config;
+ _serverSignature = serverSignature;
+
+ Start();
+ }
+
+ private IEnumerable<UpnpDevice> Devices
+ {
+ get
+ {
+ UpnpDevice[] devs;
+ lock (_devices)
+ {
+ devs = _devices.Values.SelectMany(i => i).ToArray();
+ }
+ return devs;
+ }
+ }
+
+ private void Start()
+ {
+ _udpClient = new UdpClient();
+ _udpClient.Client.UseOnlyOverlappedIO = true;
+ _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ _udpClient.ExclusiveAddressUse = false;
+ _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, SSDPPort));
+ _udpClient.JoinMulticastGroup(_ssdpIp, 2);
+ _logger.Info("SSDP service started");
+ Receive();
+ }
+
+ private void Receive()
+ {
+ try
+ {
+ _udpClient.BeginReceive(ReceiveCallback, null);
+ }
+ catch (ObjectDisposedException)
+ {
+ }
+ }
+
+ private void ReceiveCallback(IAsyncResult result)
+ {
+ try
+ {
+ var endpoint = new IPEndPoint(IPAddress.None, SSDPPort);
+ var received = _udpClient.EndReceive(result, ref endpoint);
+
+ if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ {
+ _logger.Debug("{0} - SSDP Received a datagram", endpoint);
+ }
+
+ using (var reader = new StreamReader(new MemoryStream(received), Encoding.ASCII))
+ {
+ var proto = (reader.ReadLine() ?? string.Empty).Trim();
+ var method = proto.Split(new[] { ' ' }, 2)[0];
+ var headers = new Headers();
+ for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
+ {
+ line = line.Trim();
+ if (string.IsNullOrEmpty(line))
+ {
+ break;
+ }
+ var parts = line.Split(new char[] { ':' }, 2);
+ headers[parts[0]] = parts[1].Trim();
+ }
+
+ if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ {
+ _logger.Debug("{0} - Datagram method: {1}", endpoint, method);
+ //_logger.Debug(headers);
+ }
+
+ if (string.Equals(method, "M-SEARCH", StringComparison.OrdinalIgnoreCase))
+ {
+ RespondToSearch(endpoint, headers["st"]);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Failed to read SSDP message", ex);
+ }
+
+ if (!_isDisposed)
+ {
+ Receive();
+ }
+ }
+
+ private void RespondToSearch(IPEndPoint endpoint, string req)
+ {
+ if (req == "ssdp:all")
+ {
+ req = null;
+ }
+
+ if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ {
+ _logger.Debug("RespondToSearch");
+ }
+
+ foreach (var d in Devices)
+ {
+ if (!string.IsNullOrEmpty(req) && req != d.Type)
+ {
+ continue;
+ }
+
+ SendSearchResponse(endpoint, d);
+ }
+ }
+
+ private void SendSearchResponse(IPEndPoint endpoint, UpnpDevice dev)
+ {
+ var headers = new RawHeaders();
+ headers.Add("CACHE-CONTROL", "max-age = 600");
+ headers.Add("DATE", DateTime.Now.ToString("R"));
+ headers.Add("EXT", "");
+ headers.Add("LOCATION", dev.Descriptor.ToString());
+ headers.Add("SERVER", _serverSignature);
+ headers.Add("ST", dev.Type);
+ headers.Add("USN", dev.USN);
+
+ SendDatagram(endpoint, String.Format("HTTP/1.1 200 OK\r\n{0}\r\n", headers.HeaderBlock), false);
+ _logger.Info("{1} - Responded to a {0} request", dev.Type, endpoint);
+ }
+
+ private void SendDatagram(IPEndPoint endpoint, string msg, bool sticky)
+ {
+ if (_isDisposed)
+ {
+ return;
+ }
+ //var dgram = new Datagram(endpoint, msg, sticky);
+ //if (messageQueue.Count == 0)
+ //{
+ // dgram.Send();
+ //}
+ //messageQueue.Enqueue(dgram);
+ //queueTimer.Enabled = true;
+ }
+
+ private void NotifyAll()
+ {
+ _logger.Debug("NotifyAll");
+ foreach (var d in Devices)
+ {
+ NotifyDevice(d, "alive", false);
+ }
+ }
+
+ private void NotifyDevice(UpnpDevice dev, string type, bool sticky)
+ {
+ _logger.Debug("NotifyDevice");
+ var headers = new RawHeaders();
+ headers.Add("HOST", "239.255.255.250:1900");
+ headers.Add("CACHE-CONTROL", "max-age = 600");
+ headers.Add("LOCATION", dev.Descriptor.ToString());
+ headers.Add("SERVER", _serverSignature);
+ headers.Add("NTS", "ssdp:" + type);
+ headers.Add("NT", dev.Type);
+ headers.Add("USN", dev.USN);
+
+ SendDatagram(_ssdpEndp, String.Format("NOTIFY * HTTP/1.1\r\n{0}\r\n", headers.HeaderBlock), sticky);
+ _logger.Debug("{0} said {1}", dev.USN, type);
+ }
+
+ private void RegisterNotification(Guid UUID, Uri Descriptor)
+ {
+ List<UpnpDevice> list;
+ lock (_devices)
+ {
+ if (!_devices.TryGetValue(UUID, out list))
+ {
+ _devices.Add(UUID, list = new List<UpnpDevice>());
+ }
+ }
+
+ foreach (var t in new[] { "upnp:rootdevice", "urn:schemas-upnp-org:device:MediaServer:1", "urn:schemas-upnp-org:service:ContentDirectory:1", "uuid:" + UUID })
+ {
+ list.Add(new UpnpDevice(UUID, t, Descriptor));
+ }
+
+ NotifyAll();
+ _logger.Debug("Registered mount {0}", UUID);
+ }
+
+ internal void UnregisterNotification(Guid UUID)
+ {
+ List<UpnpDevice> dl;
+ lock (_devices)
+ {
+ if (!_devices.TryGetValue(UUID, out dl))
+ {
+ return;
+ }
+ _devices.Remove(UUID);
+ }
+ foreach (var d in dl)
+ {
+ NotifyDevice(d, "byebye", true);
+ }
+ _logger.Debug("Unregistered mount {0}", UUID);
+ }
+
+ public void Dispose()
+ {
+ _isDisposed = true;
+ //while (messageQueue.Count != 0)
+ //{
+ // datagramPosted.WaitOne();
+ //}
+
+ _udpClient.DropMulticastGroup(_ssdpIp);
+ _udpClient.Close();
+
+ //notificationTimer.Enabled = false;
+ //queueTimer.Enabled = false;
+ //notificationTimer.Dispose();
+ //queueTimer.Dispose();
+ //datagramPosted.Dispose();
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Server/UpnpDevice.cs b/MediaBrowser.Dlna/Server/UpnpDevice.cs
new file mode 100644
index 000000000..96e37eb07
--- /dev/null
+++ b/MediaBrowser.Dlna/Server/UpnpDevice.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace MediaBrowser.Dlna.Server
+{
+ public sealed class UpnpDevice
+ {
+ public readonly Uri Descriptor;
+ public readonly string Type;
+ public readonly string USN;
+ public readonly Guid Uuid;
+
+ public UpnpDevice(Guid aUuid, string aType, Uri aDescriptor)
+ {
+ Uuid = aUuid;
+ Type = aType;
+ Descriptor = aDescriptor;
+
+ if (Type.StartsWith("uuid:"))
+ {
+ USN = Type;
+ }
+ else
+ {
+ USN = String.Format("uuid:{0}::{1}", Uuid.ToString(), Type);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index 91ac67a1f..8de54f34a 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -1030,7 +1030,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="timer">The timer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task CreateLiveTvTimerAsync(TimerInfoDto timer, CancellationToken cancellationToken);
+ Task CreateLiveTvTimerAsync(BaseTimerInfoDto timer, CancellationToken cancellationToken);
/// <summary>
/// Updates the live tv timer asynchronous.
diff --git a/MediaBrowser.Model/Configuration/DlnaOptions.cs b/MediaBrowser.Model/Configuration/DlnaOptions.cs
index b2503ebc7..00fdaa444 100644
--- a/MediaBrowser.Model/Configuration/DlnaOptions.cs
+++ b/MediaBrowser.Model/Configuration/DlnaOptions.cs
@@ -4,11 +4,15 @@ namespace MediaBrowser.Model.Configuration
public class DlnaOptions
{
public bool EnablePlayTo { get; set; }
- public bool EnablePlayToDebugLogging { get; set; }
+ public bool EnableServer { get; set; }
+ public bool EnableDebugLogging { get; set; }
+ public int ClientDiscoveryIntervalSeconds { get; set; }
public DlnaOptions()
{
EnablePlayTo = true;
+ EnableServer = true;
+ ClientDiscoveryIntervalSeconds = 60;
}
}
}
diff --git a/MediaBrowser.Model/Dto/StreamOptions.cs b/MediaBrowser.Model/Dto/StreamOptions.cs
index 17fd06cb6..c38707e53 100644
--- a/MediaBrowser.Model/Dto/StreamOptions.cs
+++ b/MediaBrowser.Model/Dto/StreamOptions.cs
@@ -10,7 +10,7 @@
/// Omit to copy
/// </summary>
/// <value>The video codec.</value>
- public VideoCodecs? VideoCodec { get; set; }
+ public string VideoCodec { get; set; }
/// <summary>
/// Gets or sets the video bit rate.
@@ -113,7 +113,7 @@
/// Omit to copy the original stream
/// </summary>
/// <value>The audio encoding format.</value>
- public AudioCodecs? AudioCodec { get; set; }
+ public string AudioCodec { get; set; }
/// <summary>
/// Gets or sets the item id.
@@ -158,68 +158,4 @@
/// <value>The device id.</value>
public string DeviceId { get; set; }
}
-
- /// <summary>
- /// These are the codecs the api is capable of encoding to
- /// </summary>
- public enum AudioCodecs
- {
- /// <summary>
- /// The aac
- /// </summary>
- Aac,
- /// <summary>
- /// The MP3
- /// </summary>
- Mp3,
- /// <summary>
- /// The vorbis
- /// </summary>
- Vorbis,
- /// <summary>
- /// The wma
- /// </summary>
- Wma,
- /// <summary>
- /// The copy
- /// </summary>
- Copy
- }
-
- /// <summary>
- /// Enum VideoCodecs
- /// </summary>
- public enum VideoCodecs
- {
- H263,
-
- /// <summary>
- /// The H264
- /// </summary>
- H264,
-
- /// <summary>
- /// The mpeg4
- /// </summary>
- Mpeg4,
-
- /// <summary>
- /// The theora
- /// </summary>
- Theora,
-
- /// <summary>
- /// The VPX
- /// </summary>
- Vpx,
-
- /// <summary>
- /// The WMV
- /// </summary>
- Wmv,
- /// <summary>
- /// The copy
- /// </summary>
- Copy
- }
}
diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
index 0198cc399..393233c1b 100644
--- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
@@ -1,81 +1,15 @@
-using System;
+using MediaBrowser.Model.Entities;
+using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
-using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.LiveTv
{
[DebuggerDisplay("Name = {Name}")]
- public class SeriesTimerInfoDto : INotifyPropertyChanged
+ public class SeriesTimerInfoDto : BaseTimerInfoDto
{
/// <summary>
- /// Id of the recording.
- /// </summary>
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the external identifier.
- /// </summary>
- /// <value>The external identifier.</value>
- public string ExternalId { get; set; }
-
- /// <summary>
- /// ChannelId of the recording.
- /// </summary>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the service.
- /// </summary>
- /// <value>The name of the service.</value>
- public string ServiceName { get; set; }
-
- /// <summary>
- /// Gets or sets the external channel identifier.
- /// </summary>
- /// <value>The external channel identifier.</value>
- public string ExternalChannelId { get; set; }
-
- /// <summary>
- /// ChannelName of the recording.
- /// </summary>
- public string ChannelName { get; set; }
-
- /// <summary>
- /// Gets or sets the program identifier.
- /// </summary>
- /// <value>The program identifier.</value>
- public string ProgramId { get; set; }
-
- /// <summary>
- /// Gets or sets the external program identifier.
- /// </summary>
- /// <value>The external program identifier.</value>
- public string ExternalProgramId { get; set; }
-
- /// <summary>
- /// Name of the recording.
- /// </summary>
- public string Name { get; set; }
-
- /// <summary>
- /// Description of the recording.
- /// </summary>
- public string Overview { get; set; }
-
- /// <summary>
- /// The start date of the recording, in UTC.
- /// </summary>
- public DateTime StartDate { get; set; }
-
- /// <summary>
- /// The end date of the recording, in UTC.
- /// </summary>
- public DateTime EndDate { get; set; }
-
- /// <summary>
/// Gets or sets a value indicating whether [record any time].
/// </summary>
/// <value><c>true</c> if [record any time]; otherwise, <c>false</c>.</value>
@@ -106,36 +40,6 @@ namespace MediaBrowser.Model.LiveTv
public DayPattern? DayPattern { get; set; }
/// <summary>
- /// Gets or sets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public int Priority { get; set; }
-
- /// <summary>
- /// Gets or sets the pre padding seconds.
- /// </summary>
- /// <value>The pre padding seconds.</value>
- public int PrePaddingSeconds { get; set; }
-
- /// <summary>
- /// Gets or sets the post padding seconds.
- /// </summary>
- /// <value>The post padding seconds.</value>
- public int PostPaddingSeconds { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is pre padding required.
- /// </summary>
- /// <value><c>true</c> if this instance is pre padding required; otherwise, <c>false</c>.</value>
- public bool IsPrePaddingRequired { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is post padding required.
- /// </summary>
- /// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
- public bool IsPostPaddingRequired { get; set; }
-
- /// <summary>
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
@@ -156,7 +60,5 @@ namespace MediaBrowser.Model.LiveTv
ImageTags = new Dictionary<ImageType, Guid>();
Days = new List<DayOfWeek>();
}
-
- public event PropertyChangedEventHandler PropertyChanged;
}
}
diff --git a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
index a330f44d8..137c95719 100644
--- a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
@@ -3,9 +3,48 @@ using System.ComponentModel;
namespace MediaBrowser.Model.LiveTv
{
- public class TimerInfoDto : INotifyPropertyChanged
+ public class TimerInfoDto : BaseTimerInfoDto
{
/// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public RecordingStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the series timer identifier.
+ /// </summary>
+ /// <value>The series timer identifier.</value>
+ public string SeriesTimerId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the external series timer identifier.
+ /// </summary>
+ /// <value>The external series timer identifier.</value>
+ public string ExternalSeriesTimerId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the run time ticks.
+ /// </summary>
+ /// <value>The run time ticks.</value>
+ public long? RunTimeTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the program information.
+ /// </summary>
+ /// <value>The program information.</value>
+ public ProgramInfoDto ProgramInfo { get; set; }
+
+ }
+
+ public class BaseTimerInfoDto : INotifyPropertyChanged
+ {
+ /// <summary>
+ /// Occurs when a property value changes.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
/// Id of the recording.
/// </summary>
public string Id { get; set; }
@@ -26,19 +65,13 @@ namespace MediaBrowser.Model.LiveTv
/// </summary>
/// <value>The external channel identifier.</value>
public string ExternalChannelId { get; set; }
-
+
/// <summary>
/// ChannelName of the recording.
/// </summary>
public string ChannelName { get; set; }
/// <summary>
- /// Gets or sets the name of the service.
- /// </summary>
- /// <value>The name of the service.</value>
- public string ServiceName { get; set; }
-
- /// <summary>
/// Gets or sets the program identifier.
/// </summary>
/// <value>The program identifier.</value>
@@ -49,7 +82,7 @@ namespace MediaBrowser.Model.LiveTv
/// </summary>
/// <value>The external program identifier.</value>
public string ExternalProgramId { get; set; }
-
+
/// <summary>
/// Name of the recording.
/// </summary>
@@ -71,22 +104,16 @@ namespace MediaBrowser.Model.LiveTv
public DateTime EndDate { get; set; }
/// <summary>
- /// Gets or sets the status.
- /// </summary>
- /// <value>The status.</value>
- public RecordingStatus Status { get; set; }
-
- /// <summary>
- /// Gets or sets the series timer identifier.
+ /// Gets or sets the name of the service.
/// </summary>
- /// <value>The series timer identifier.</value>
- public string SeriesTimerId { get; set; }
+ /// <value>The name of the service.</value>
+ public string ServiceName { get; set; }
/// <summary>
- /// Gets or sets the external series timer identifier.
+ /// Gets or sets the priority.
/// </summary>
- /// <value>The external series timer identifier.</value>
- public string ExternalSeriesTimerId { get; set; }
+ /// <value>The priority.</value>
+ public int Priority { get; set; }
/// <summary>
/// Gets or sets the pre padding seconds.
@@ -111,28 +138,5 @@ namespace MediaBrowser.Model.LiveTv
/// </summary>
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
public bool IsPostPaddingRequired { get; set; }
-
- /// <summary>
- /// Gets or sets the run time ticks.
- /// </summary>
- /// <value>The run time ticks.</value>
- public long? RunTimeTicks { get; set; }
-
- /// <summary>
- /// Gets or sets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public int Priority { get; set; }
-
- /// <summary>
- /// Gets or sets the program information.
- /// </summary>
- /// <value>The program information.</value>
- public ProgramInfoDto ProgramInfo { get; set; }
-
- /// <summary>
- /// Occurs when a property value changes.
- /// </summary>
- public event PropertyChangedEventHandler PropertyChanged;
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index ad2852a91..098d1295f 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
CreateRules(device);
}
- catch (Exception ex)
+ catch (Exception)
{
//_logger.ErrorException("Error creating port forwarding rules", ex);
}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 879fbc1b6..e49244edf 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -266,7 +266,7 @@ namespace MediaBrowser.ServerApplication
{
MigrateUserFolders();
}
- catch (IOException ex)
+ catch (IOException)
{
}
@@ -498,7 +498,7 @@ namespace MediaBrowser.ServerApplication
var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
RegisterSingleInstance<IAppThemeManager>(appThemeManager);
- var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager);
+ var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, JsonSerializer);
RegisterSingleInstance<IDlnaManager>(dlnaManager);
var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index 765cae612..ea1905bad 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -3809,7 +3809,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
var deferred = $.Deferred();
var msg = [itemId, canSeek, queueableMediaTypes];
-
+
if (mediaSourceId) {
msg.push(mediaSourceId);
}
@@ -4029,7 +4029,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
self.createPackageReview = function (review) {
- var url = self.getUrl("PackageReviews/" + review.id, review);
+ var url = self.getUrl("Packages/Reviews/" + review.id, review);
return self.ajax({
type: "POST",
@@ -4058,7 +4058,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
options.ForceTitle = true;
}
- var url = self.getUrl("PackageReviews/" + packageId, options);
+ var url = self.getUrl("Packages/" + packageId + "Reviews", options);
return self.ajax({
type: "GET",
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 7396527bb..a5074d3c8 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.ApiClient.Javascript" version="3.0.247" targetFramework="net45" />
+ <package id="MediaBrowser.ApiClient.Javascript" version="3.0.248" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 12219e81d..c550b350c 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
- <version>3.0.343</version>
+ <version>3.0.345</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.343" />
+ <dependency id="MediaBrowser.Common" version="3.0.345" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.4.1" />
<dependency id="sharpcompress" version="0.10.2" />
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 495dc3f2b..a6fa5c152 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.343</version>
+ <version>3.0.345</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 398adc207..cc87b0030 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.343</version>
+ <version>3.0.345</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.343" />
+ <dependency id="MediaBrowser.Common" version="3.0.345" />
</dependencies>
</metadata>
<files>