diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 1e9f2f7a2f..8bc06b6577 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -211,12 +211,7 @@ namespace MediaBrowser.Api
private void UpdateItem(BaseItemDto request, BaseItem item)
{
item.Name = request.Name;
-
- // Only set the forced value if they changed it, or there's already one
- if (!string.Equals(item.SortName, request.SortName) || !string.IsNullOrEmpty(item.ForcedSortName))
- {
- item.ForcedSortName = request.SortName;
- }
+ item.ForcedSortName = request.ForcedSortName;
var hasBudget = item as IHasBudget;
if (hasBudget != null)
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index b3f6cbd976..60270a3895 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -10,8 +10,7 @@ namespace MediaBrowser.Api
///
/// Class GetCultures
///
- [Route("/Localization/Cultures", "GET")]
- [Api(Description = "Gets known cultures")]
+ [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
public class GetCultures : IReturn>
{
}
@@ -19,8 +18,7 @@ namespace MediaBrowser.Api
///
/// Class GetCountries
///
- [Route("/Localization/Countries", "GET")]
- [Api(Description = "Gets known countries")]
+ [Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
public class GetCountries : IReturn>
{
}
@@ -28,8 +26,7 @@ namespace MediaBrowser.Api
///
/// Class ParentalRatings
///
- [Route("/Localization/ParentalRatings", "GET")]
- [Api(Description = "Gets known parental ratings")]
+ [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
public class GetParentalRatings : IReturn>
{
}
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index f9b7608696..204a7aab45 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().ToList();
+ var movies = user.RootFolder.GetRecursiveChildren(user).OfType().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 99a4d4fa7e..6243bf25f4 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>
{
///
@@ -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 45a16347bc..a71a85395a 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
{
[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
{
[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
{
[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 b2de908d9f..94ff1b62e2 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
{
///
/// Class InstallPackage
///
- [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
{
///
@@ -57,8 +56,7 @@ namespace MediaBrowser.Api
///
/// Class InstallPackage
///
- [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>
{
///
@@ -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>(result);
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index 793b666ea0..948a67f16f 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api
///
/// Class GetPackage
///
- [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
{
///
@@ -36,8 +35,7 @@ namespace MediaBrowser.Api
///
/// Class GetPackages
///
- [Route("/Packages", "GET")]
- [Api(("Gets available packages"))]
+ [Route("/Packages", "GET", Summary = "Gets available packages")]
public class GetPackages : IReturn>
{
///
@@ -57,8 +55,7 @@ namespace MediaBrowser.Api
///
/// Class GetPackageVersionUpdates
///
- [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>
{
///
@@ -72,8 +69,7 @@ namespace MediaBrowser.Api
///
/// Class InstallPackage
///
- [Route("/Packages/Installed/{Name}", "POST")]
- [Api(("Installs a package"))]
+ [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")]
public class InstallPackage : IReturnVoid
{
///
@@ -108,8 +104,7 @@ namespace MediaBrowser.Api
///
/// Class CancelPackageInstallation
///
- [Route("/Packages/Installing/{Id}", "DELETE")]
- [Api(("Cancels a package installation"))]
+ [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")]
public class CancelPackageInstallation : IReturnVoid
{
///
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 1001980ec1..7dcb06f7b3 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,16 +734,23 @@ 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";
@@ -1162,18 +1168,23 @@ namespace MediaBrowser.Api.Playback
protected double? GetFramerateParam(StreamState state)
{
- if (state.VideoRequest != null && state.VideoRequest.Framerate.HasValue)
+ if (state.VideoRequest != null)
{
- return state.VideoRequest.Framerate.Value;
- }
-
- if (state.VideoStream != null)
- {
- var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate;
-
- if (contentRate.HasValue && contentRate.Value > 23.976)
+ if (state.VideoRequest.Framerate.HasValue)
{
- return 23.976;
+ return state.VideoRequest.Framerate.Value;
+ }
+
+ var maxrate = state.VideoRequest.MaxFramerate ?? 23.976;
+
+ if (state.VideoStream != null)
+ {
+ var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate;
+
+ if (contentRate.HasValue && contentRate.Value > maxrate)
+ {
+ return maxrate;
+ }
}
}
@@ -1201,77 +1212,102 @@ 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)
{
- if (videoRequest != null)
- {
- videoRequest.VideoCodec = (VideoCodecs)Enum.Parse(typeof(VideoCodecs), val, true);
- }
+ request.MediaSourceId = val;
}
else if (i == 3)
{
- request.AudioCodec = (AudioCodecs)Enum.Parse(typeof(AudioCodecs), val, true);
+ request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
}
else if (i == 4)
+ {
+ if (videoRequest != null)
+ {
+ videoRequest.VideoCodec = val;
+ }
+ }
+ else if (i == 5)
+ {
+ request.AudioCodec = val;
+ }
+ 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)
+ {
+ videoRequest.MaxWidth = int.Parse(val, UsCulture);
+ }
+ }
+ else if (i == 12)
+ {
+ if (videoRequest != null)
+ {
+ videoRequest.MaxHeight = int.Parse(val, UsCulture);
+ }
+ }
+ else if (i == 13)
+ {
+ if (videoRequest != null)
+ {
+ videoRequest.Framerate = int.Parse(val, UsCulture);
+ }
+ }
+ else if (i == 14)
{
if (videoRequest != null)
{
request.StartTimeTicks = long.Parse(val, UsCulture);
}
}
- else if (i == 10)
+ else if (i == 15)
{
if (videoRequest != null)
{
videoRequest.Profile = val;
}
}
- else if (i == 11)
+ else if (i == 16)
{
if (videoRequest != null)
{
videoRequest.Level = val;
}
}
- else if (i == 12)
- {
- request.ForcedMimeType = val;
- }
}
}
@@ -1297,7 +1333,7 @@ namespace MediaBrowser.Api.Playback
var url = Request.PathInfo;
- if (!request.AudioCodec.HasValue)
+ if (string.IsNullOrEmpty(request.AudioCodec))
{
request.AudioCodec = InferAudioCodec(url);
}
@@ -1425,7 +1461,7 @@ namespace MediaBrowser.Api.Playback
if (videoRequest != null)
{
- if (!videoRequest.VideoCodec.HasValue)
+ if (string.IsNullOrEmpty(videoRequest.VideoCodec))
{
videoRequest.VideoCodec = InferVideoCodec(url);
}
@@ -1532,41 +1568,41 @@ namespace MediaBrowser.Api.Playback
///
/// The URL.
/// System.Nullable{AudioCodecs}.
- 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 +1613,28 @@ namespace MediaBrowser.Api.Playback
///
/// The URL.
/// System.Nullable{VideoCodecs}.
- 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 aec271ff20..eb8f415e0d 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 121957ecc9..66e8b0d149 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 8ae61b5219..9cb989fc21 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))
{
- case AudioCodecs.Aac:
- return ".aac";
- case AudioCodecs.Mp3:
- return ".mp3";
- case AudioCodecs.Vorbis:
- return ".ogg";
- case AudioCodecs.Wma:
- return ".wma";
+ 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))
+ {
+ return ".wma";
}
}
}
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index df52e5e3ee..8db5920f6b 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
///
/// The audio codec.
[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; }
///
/// 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; }
+
///
/// Gets or sets the audio sample rate.
///
@@ -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
///
/// The video codec.
[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; }
///
/// Gets or sets the video bit rate.
@@ -145,6 +145,9 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "Framerate", Description = "Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements.", IsRequired = false, DataType = "double", ParameterType = "query", Verb = "GET")]
public double? Framerate { get; set; }
+ [ApiMember(Name = "MaxFramerate", Description = "Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements.", IsRequired = false, DataType = "double", ParameterType = "query", Verb = "GET")]
+ public double? MaxFramerate { get; set; }
+
///
/// Gets or sets the profile.
///
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 88daf9f623..ecc5c93ef2 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 e66f432df8..31463dc3f4 100644
--- a/MediaBrowser.Api/PluginService.cs
+++ b/MediaBrowser.Api/PluginService.cs
@@ -18,8 +18,7 @@ namespace MediaBrowser.Api
///
/// Class Plugins
///
- [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>
{
}
@@ -27,8 +26,7 @@ namespace MediaBrowser.Api
///
/// Class UninstallPlugin
///
- [Route("/Plugins/{Id}", "DELETE")]
- [Api(("Uninstalls a plugin"))]
+ [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
public class UninstallPlugin : IReturnVoid
{
///
@@ -42,8 +40,7 @@ namespace MediaBrowser.Api
///
/// Class GetPluginConfiguration
///
- [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
{
///
@@ -57,8 +54,7 @@ namespace MediaBrowser.Api
///
/// Class UpdatePluginConfiguration
///
- [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
{
///
@@ -78,8 +74,7 @@ namespace MediaBrowser.Api
///
/// Class GetPluginSecurityInfo
///
- [Route("/Plugins/SecurityInfo", "GET")]
- [Api(("Gets plugin registration information"))]
+ [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information")]
public class GetPluginSecurityInfo : IReturn
{
}
@@ -87,14 +82,12 @@ namespace MediaBrowser.Api
///
/// Class UpdatePluginSecurityInfo
///
- [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 c143635bfa..0d3f5dfcdf 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;
+
///
/// Gets the data to send.
///
@@ -46,7 +48,25 @@ namespace MediaBrowser.Api.ScheduledTasks
/// Task{IEnumerable{TaskInfo}}.
protected override Task> 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>(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 f46c6b8e30..662c728e46 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
///
/// Class GetSearchHints
///
- [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
{
///
@@ -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 e73e3490ec..a509c876ce 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api
///
/// Class GetSessions
///
- [Route("/Sessions", "GET")]
- [Api(("Gets a list of sessions"))]
+ [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
public class GetSessions : IReturn>
{
///
@@ -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; }
}
///
/// Class BrowseTo
///
- [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
{
///
@@ -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
{
///
@@ -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
{
///
@@ -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
{
///
@@ -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
{
///
@@ -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
{
///
diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs
index 9f5f3716ec..2f0741434a 100644
--- a/MediaBrowser.Api/SystemService.cs
+++ b/MediaBrowser.Api/SystemService.cs
@@ -8,8 +8,7 @@ namespace MediaBrowser.Api
///
/// Class GetSystemInfo
///
- [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
{
@@ -18,18 +17,16 @@ namespace MediaBrowser.Api
///
/// Class RestartApplication
///
- [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
{
}
-
+
///
/// Class SystemInfoService
///
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index a805b7b551..7fa586a7d7 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
///
/// Class GetNextUpEpisodes
///
- [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, IHasItemFields
{
///
@@ -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, IHasItemFields
{
///
@@ -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, IHasItemFields
{
///
@@ -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, IHasItemFields
{
///
@@ -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 18c3bd0962..2f1b161078 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
///
/// Class GetUsers
///
- [Route("/Users", "GET")]
- [Api(Description = "Gets a list of users")]
+ [Route("/Users", "GET", Summary = "Gets a list of users")]
public class GetUsers : IReturn>
{
[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>
{
}
@@ -37,8 +35,7 @@ namespace MediaBrowser.Api
///
/// Class GetUser
///
- [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
{
///
@@ -52,8 +49,7 @@ namespace MediaBrowser.Api
///
/// Class DeleteUser
///
- [Route("/Users/{Id}", "DELETE")]
- [Api(Description = "Deletes a user")]
+ [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
public class DeleteUser : IReturnVoid
{
///
@@ -67,8 +63,7 @@ namespace MediaBrowser.Api
///
/// Class AuthenticateUser
///
- [Route("/Users/{Id}/Authenticate", "POST")]
- [Api(Description = "Authenticates a user")]
+ [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")]
public class AuthenticateUser : IReturn
{
///
@@ -89,8 +84,7 @@ namespace MediaBrowser.Api
///
/// Class AuthenticateUser
///
- [Route("/Users/AuthenticateByName", "POST")]
- [Api(Description = "Authenticates a user")]
+ [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")]
public class AuthenticateUserByName : IReturn
{
///
@@ -111,8 +105,7 @@ namespace MediaBrowser.Api
///
/// Class UpdateUserPassword
///
- [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
{
///
@@ -143,8 +136,7 @@ namespace MediaBrowser.Api
///
/// Class UpdateUser
///
- [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
///
/// Class CreateUser
///
- [Route("/Users", "POST")]
- [Api(Description = "Creates a user")]
+ [Route("/Users", "POST", Summary = "Creates a user")]
public class CreateUser : UserDto, IReturn
{
}
diff --git a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
index 4ff34cfa12..33d3f368b6 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
/// The type of the T state type.
public abstract class BasePeriodicWebSocketListener : IWebSocketListener, IDisposable
where TStateType : class, new()
+ where TReturnDataType : class
{
///
/// The _active connections
@@ -144,12 +145,15 @@ namespace MediaBrowser.Common.Net
var data = await GetDataToSend(tuple.Item4).ConfigureAwait(false);
- await connection.SendAsync(new WebSocketMessage
+ if (data != null)
{
- MessageType = Name,
- Data = data
+ await connection.SendAsync(new WebSocketMessage
+ {
+ 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 a4592e654a..2b9a40ea06 100644
--- a/MediaBrowser.Controller/Dlna/CodecProfile.cs
+++ b/MediaBrowser.Controller/Dlna/CodecProfile.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Controller.Dlna
@@ -6,18 +7,25 @@ namespace MediaBrowser.Controller.Dlna
public class CodecProfile
{
public CodecType Type { get; set; }
- public List Conditions { get; set; }
+ public ProfileCondition[] Conditions { get; set; }
public string Codec { get; set; }
public CodecProfile()
{
- Conditions = new List();
+ Conditions = new ProfileCondition[] {};
}
public List GetCodecs()
{
return (Codec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
}
+
+ public bool ContainsCodec(string codec)
+ {
+ var codecs = GetCodecs();
+
+ return codecs.Count == 0 || codecs.Contains(codec, StringComparer.OrdinalIgnoreCase);
+ }
}
public enum CodecType
@@ -57,9 +65,12 @@ namespace MediaBrowser.Controller.Dlna
Width,
Height,
Has64BitOffsets,
+ VideoBitDepth,
VideoBitrate,
VideoFramerate,
VideoLevel,
- VideoProfile
+ VideoPacketLength,
+ VideoProfile,
+ VideoTimestamp
}
}
diff --git a/MediaBrowser.Controller/Dlna/ContainerProfile.cs b/MediaBrowser.Controller/Dlna/ContainerProfile.cs
new file mode 100644
index 0000000000..3bd3c9eaf6
--- /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 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 20c94ad50b..461c77537c 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.
///
/// The headers.
- public List Headers { get; set; }
+ public HttpHeaderInfo[] Headers { get; set; }
public DeviceIdentification()
{
- Headers = new List();
+ 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 49568e7d43..f3de1bc34a 100644
--- a/MediaBrowser.Controller/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Controller/Dlna/DeviceProfile.cs
@@ -20,13 +20,15 @@ namespace MediaBrowser.Controller.Dlna
///
/// The transcoding profiles.
public TranscodingProfile[] TranscodingProfiles { get; set; }
-
+
///
/// Gets or sets the direct play profiles.
///
/// The direct play profiles.
public DirectPlayProfile[] DirectPlayProfiles { get; set; }
+ public ContainerProfile[] ContainerProfiles { get; set; }
+
///
/// Gets or sets the identification.
///
@@ -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; }
+
///
/// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
///
@@ -62,13 +67,14 @@ namespace MediaBrowser.Controller.Dlna
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 53d32a2f8d..686b31287e 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 Conditions { get; set; }
-
- public DirectPlayProfile()
+ public List GetContainers()
{
- Conditions = new List();
-
- Containers = new string[] { };
+ return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
}
public List GetAudioCodecs()
diff --git a/MediaBrowser.Controller/Dlna/MediaProfile.cs b/MediaBrowser.Controller/Dlna/MediaProfile.cs
index 5fa41b18aa..1d2613face 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 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 1073f74aaf..007cb632e4 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
@@ -15,12 +14,14 @@ namespace MediaBrowser.Controller.Dlna
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
- public List Settings { get; set; }
+ public TranscodingSetting[] Settings { get; set; }
public TranscodingProfile()
{
- Settings = new List();
+ Settings = new TranscodingSetting[] { };
}
+
+ public bool EnableMpegtsM2TsMode { get; set; }
}
public class TranscodingSetting
@@ -31,8 +32,7 @@ namespace MediaBrowser.Controller.Dlna
public enum TranscodingSettingType
{
- Profile = 0,
- MaxAudioChannels = 1
+ VideoProfile = 0
}
public enum TranscodeSeekInfo
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index b51824bdb9..5e6297d060 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -79,6 +79,7 @@
+
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index 24e9d83a03..c6da865cd7 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,989 +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 GetProfiles()
{
- var list = new List();
-
- list.Add(new DeviceProfile
+ var list = new List
{
- 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",
-
- 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 List
- {
- 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 List
- {
- new TranscodingSetting
- {
- Name = TranscodingSettingType.MaxAudioChannels,
- Value = "6"
- }
- }
- },
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- },
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- VideoCodec = "mpeg4",
- AudioCodec = "ac3,mp3",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"avi"},
- VideoCodec = "h264",
- AudioCodec = "aac",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp4", "mov"},
- VideoCodec = "h264,mpeg4",
- AudioCodec = "aac,ac3",
- Type = DlnaProfileType.Video,
-
- Conditions = new List
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Has64BitOffsets, Value = "false", IsRequired=false}
- }
- },
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- VideoCodec = "wmv2,wmv3,vc1",
- AudioCodec = "wmav2,wmapro",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Containers = new[]{"asf"},
- AudioCodec = "wmav2,wmapro,wmavoice",
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"mp3"},
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Containers = new[]{"jpeg"},
- Type = DlnaProfileType.Photo,
-
- Conditions = new List
- {
- 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 ="avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- }
- },
-
- CodecProfiles = new[]
- {
- new CodecProfile
- {
- Type = CodecType.VideoCodec,
- Codec = "mpeg4",
- Conditions = new List
- {
- 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 List
- {
- 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 List
- {
- 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 List
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.AudioChannels, Value = "6", IsRequired=false}
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.VideoAudioCodec,
- Codec = "aac",
- Conditions = new List
- {
- new ProfileCondition{ Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.AudioChannels, Value = "6", IsRequired=false},
- new ProfileCondition{ Condition = ProfileConditionType.Equals, Property = ProfileConditionValue.AudioProfile, Value = "lc", IsRequired=false}
- }
- }
- }
- });
-
- 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
- {
- 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
- {
- 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
- {
- 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
- {
- 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
- },
- }
- });
+ 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;
@@ -1003,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)
@@ -1046,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 800fb1b236..bea281b614 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -81,7 +81,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -97,9 +118,7 @@
MediaBrowser.Model
-
-
-
+