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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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")]
public bool Static { get; set; }
[ApiMember(Name = "DeviceProfileId", Description = "Optional. The dlna device profile id to utilize.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceProfileId { get; set; }
/// <summary>
/// For testing purposes
/// </summary>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,6 @@

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

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

View file

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

View file

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

View file

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

View file

@ -1,17 +1,33 @@

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

View file

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

View file

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

View file

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

View file

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

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
{
@ -24,7 +23,18 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Gets or sets the chapters.
/// </summary>
/// <value>The chapters.</value>
public List<ChapterInfo> Chapters { get; set; }
public MediaChapter[] Chapters { get; set; }
}
public class MediaChapter
{
public int id { get; set; }
public string time_base { get; set; }
public long start { get; set; }
public string start_time { get; set; }
public long end { get; set; }
public string end_time { get; set; }
public Dictionary<string, string> tags { get; set; }
}
/// <summary>

View file

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

View file

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

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>
Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
/// <summary>
/// Sends the generic command.
/// </summary>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken);
/// <summary>
/// Sends the library update info.
/// </summary>

View file

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

View file

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

View file

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

View file

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

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
{
@ -17,27 +17,18 @@ namespace MediaBrowser.Dlna.PlayTo
public string ClientType { get; set; }
private string _displayName = string.Empty;
public string DisplayName
{
get
{
return string.IsNullOrEmpty(_displayName) ? Name : _displayName;
}
set
{
_displayName = value;
}
}
public string ModelName { get; set; }
public string ModelNumber { get; set; }
public string ModelDescription { get; set; }
public string ModelUrl { get; set; }
public string Manufacturer { get; set; }
public string SerialNumber { get; set; }
public string ManufacturerUrl { get; set; }
public string PresentationUrl { get; set; }
@ -75,7 +66,9 @@ namespace MediaBrowser.Dlna.PlayTo
ModelNumber = ModelNumber,
FriendlyName = Name,
ManufacturerUrl = ManufacturerUrl,
ModelUrl = ModelUrl
ModelUrl = ModelUrl,
ModelDescription = ModelDescription,
SerialNumber = SerialNumber
};
}
}

View file

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

View file

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

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.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Dlna.Ssdp;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -126,10 +127,9 @@ namespace MediaBrowser.Dlna.PlayTo
if (receivedBytes > 0)
{
var rawData = Encoding.UTF8.GetString(receiveBuffer, 0, receivedBytes);
var uri = SsdpHelper.ParseSsdpResponse(rawData);
var headers = SsdpHelper.ParseSsdpResponse(receiveBuffer);
TryCreateController(uri);
TryCreateController(headers);
}
}
@ -146,13 +146,20 @@ namespace MediaBrowser.Dlna.PlayTo
}, _tokenSource.Token, TaskCreationOptions.LongRunning);
}
private void TryCreateController(Uri uri)
private void TryCreateController(IDictionary<string,string> headers)
{
string location;
if (!headers.TryGetValue("Location", out location))
{
return;
}
Task.Run(async () =>
{
try
{
await CreateController(uri).ConfigureAwait(false);
await CreateController(new Uri(location)).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@ -221,46 +228,29 @@ namespace MediaBrowser.Dlna.PlayTo
if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive))
{
GetProfileSettings(device.Properties);
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, device.Properties.Name, device.Properties.UUID, device.Properties.DisplayName, uri.OriginalString, null)
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
.ConfigureAwait(false);
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
{
PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo },
SupportsFullscreenToggle = false
});
var controller = sessionInfo.SessionController as PlayToController;
if (controller == null)
{
sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager, _dlnaManager, _userManager, _appHost);
controller.Init(device);
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 string DeviceProfileName { get; set; }
public int? MaxAudioChannels { get; set; }
public int? AudioBitrate { get; set; }
@ -48,6 +46,8 @@ namespace MediaBrowser.Dlna.PlayTo
public int? MaxFramerate { get; set; }
public string DeviceProfileId { get; set; }
public PlaylistItem()
{
TranscodingSettings = new List<TranscodingSetting>();

View file

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

View file

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

View file

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

View file

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

View file

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

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
{
[XmlRoot("Profile")]
public class LgTvProfile : DefaultProfile
{
public LgTvProfile()
@ -111,7 +113,7 @@ namespace MediaBrowser.Dlna.Profiles
{
new CodecProfile
{
Type = CodecType.VideoCodec,
Type = CodecType.Video,
Codec = "mpeg4",
Conditions = new[]
@ -139,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles
new CodecProfile
{
Type = CodecType.VideoCodec,
Type = CodecType.Video,
Codec = "h264",
Conditions = new[]
@ -173,7 +175,7 @@ namespace MediaBrowser.Dlna.Profiles
new CodecProfile
{
Type = CodecType.VideoAudioCodec,
Type = CodecType.VideoAudio,
Codec = "ac3,aac,mp3",
Conditions = new[]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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 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;
}

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

View file

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

View file

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

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