This commit is contained in:
tikuf 2014-03-29 21:34:16 +11:00
commit 241be6dd93
159 changed files with 3849 additions and 1464 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,20 @@

namespace MediaBrowser.Controller.MediaEncoding
{
public class ImageEncodingOptions
{
public string InputPath { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }
public int? MaxWidth { get; set; }
public int? MaxHeight { get; set; }
public int? Quality { get; set; }
public string Format { get; set; }
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -61,7 +61,6 @@
<Compile Include="PlayTo\DeviceService.cs" /> <Compile Include="PlayTo\DeviceService.cs" />
<Compile Include="PlayTo\DidlBuilder.cs" /> <Compile Include="PlayTo\DidlBuilder.cs" />
<Compile Include="PlayTo\DlnaController.cs" /> <Compile Include="PlayTo\DlnaController.cs" />
<Compile Include="PlayTo\DlnaControllerFactory.cs" />
<Compile Include="PlayTo\Extensions.cs" /> <Compile Include="PlayTo\Extensions.cs" />
<Compile Include="PlayTo\PlaylistItem.cs"> <Compile Include="PlayTo\PlaylistItem.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
@ -70,7 +69,8 @@
<Compile Include="PlayTo\PlayToManager.cs" /> <Compile Include="PlayTo\PlayToManager.cs" />
<Compile Include="PlayTo\PlayToServerEntryPoint.cs" /> <Compile Include="PlayTo\PlayToServerEntryPoint.cs" />
<Compile Include="PlayTo\ServiceAction.cs" /> <Compile Include="PlayTo\ServiceAction.cs" />
<Compile Include="PlayTo\SsdpHelper.cs" /> <Compile Include="Profiles\Foobar2000Profile.cs" />
<Compile Include="Ssdp\SsdpHelper.cs" />
<Compile Include="PlayTo\SsdpHttpClient.cs" /> <Compile Include="PlayTo\SsdpHttpClient.cs" />
<Compile Include="PlayTo\StateVariable.cs" /> <Compile Include="PlayTo\StateVariable.cs" />
<Compile Include="PlayTo\StreamHelper.cs" /> <Compile Include="PlayTo\StreamHelper.cs" />
@ -100,7 +100,6 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server\DlnaServerEntryPoint.cs" /> <Compile Include="Server\DlnaServerEntryPoint.cs" />
<Compile Include="Server\Headers.cs" /> <Compile Include="Server\Headers.cs" />
<Compile Include="Server\RawHeaders.cs" />
<Compile Include="Server\SsdpHandler.cs" /> <Compile Include="Server\SsdpHandler.cs" />
<Compile Include="Server\UpnpDevice.cs" /> <Compile Include="Server\UpnpDevice.cs" />
</ItemGroup> </ItemGroup>
@ -118,7 +117,27 @@
<Name>MediaBrowser.Model</Name> <Name>MediaBrowser.Model</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<EmbeddedResource Include="Profiles\Xml\Denon AVR.xml" />
<EmbeddedResource Include="Profiles\Xml\foobar2000.xml" />
<EmbeddedResource Include="Profiles\Xml\LG Smart TV.xml" />
<EmbeddedResource Include="Profiles\Xml\Linksys DMA2100.xml" />
<EmbeddedResource Include="Profiles\Xml\Panasonic Viera.xml" />
<EmbeddedResource Include="Profiles\Xml\Samsung Smart TV.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player 2013.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282010%29.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282011%29.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282012%29.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282013%29.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 3.xml" />
<EmbeddedResource Include="Profiles\Xml\WDTV Live.xml" />
<EmbeddedResource Include="Profiles\Xml\Xbox 360.xml" />
<EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Profiles\Xml\Default.xml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Some files were not shown because too many files have changed in this diff Show more