mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-07 03:48:06 +02:00
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
commit
241be6dd93
159 changed files with 3849 additions and 1464 deletions
|
@ -9,16 +9,14 @@ using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
[Route("/Themes", "GET")]
|
[Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
|
||||||
[Api(Description = "Gets a list of available themes for an app")]
|
|
||||||
public class GetAppThemes : IReturn<List<AppThemeInfo>>
|
public class GetAppThemes : IReturn<List<AppThemeInfo>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string App { get; set; }
|
public string App { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Themes/Info", "GET")]
|
[Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
|
||||||
[Api(Description = "Gets an app theme")]
|
|
||||||
public class GetAppTheme : IReturn<AppTheme>
|
public class GetAppTheme : IReturn<AppTheme>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -28,8 +26,7 @@ namespace MediaBrowser.Api
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Themes/Images", "GET")]
|
[Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
|
||||||
[Api(Description = "Gets an app theme")]
|
|
||||||
public class GetAppThemeImage
|
public class GetAppThemeImage
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -45,12 +42,11 @@ namespace MediaBrowser.Api
|
||||||
public string CacheTag { get; set; }
|
public string CacheTag { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Themes", "POST")]
|
[Route("/Themes", "POST", Summary = "Saves a theme")]
|
||||||
[Api(Description = "Saves a theme")]
|
|
||||||
public class SaveTheme : AppTheme, IReturnVoid
|
public class SaveTheme : AppTheme, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AppThemeService : BaseApiService
|
public class AppThemeService : BaseApiService
|
||||||
{
|
{
|
||||||
private readonly IAppThemeManager _themeManager;
|
private readonly IAppThemeManager _themeManager;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using ServiceStack.Web;
|
using ServiceStack.Web;
|
||||||
using System;
|
using System;
|
||||||
|
@ -78,6 +79,20 @@ namespace MediaBrowser.Api
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
/// <returns>SessionInfo.</returns>
|
||||||
|
protected SessionInfo GetSession(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
|
||||||
|
|
||||||
|
return sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
|
||||||
|
string.Equals(i.Client, auth.Client) &&
|
||||||
|
string.Equals(i.ApplicationVersion, auth.Version));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To the cached result.
|
/// To the cached result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -7,8 +7,7 @@ using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
[Route("/Channels", "GET")]
|
[Route("/Channels", "GET", Summary = "Gets available channels")]
|
||||||
[Api(("Gets available channels"))]
|
|
||||||
public class GetChannels : IReturn<QueryResult<BaseItemDto>>
|
public class GetChannels : IReturn<QueryResult<BaseItemDto>>
|
||||||
{
|
{
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
|
@ -18,8 +17,7 @@ namespace MediaBrowser.Api
|
||||||
public int? Limit { get; set; }
|
public int? Limit { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Channels/{Id}/Items", "GET")]
|
[Route("/Channels/{Id}/Items", "GET", Summary = "Gets channel items")]
|
||||||
[Api(("Gets channel items"))]
|
|
||||||
public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>
|
public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>
|
||||||
{
|
{
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetConfiguration
|
/// Class GetConfiguration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/System/Configuration", "GET")]
|
[Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
|
||||||
[Api(("Gets application configuration"))]
|
|
||||||
public class GetConfiguration : IReturn<ServerConfiguration>
|
public class GetConfiguration : IReturn<ServerConfiguration>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -27,28 +26,24 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class UpdateConfiguration
|
/// Class UpdateConfiguration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/System/Configuration", "POST")]
|
[Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
|
||||||
[Api(("Updates application configuration"))]
|
|
||||||
public class UpdateConfiguration : ServerConfiguration, IReturnVoid
|
public class UpdateConfiguration : ServerConfiguration, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/System/Configuration/MetadataOptions/Default", "GET")]
|
[Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
|
||||||
[Api(("Gets a default MetadataOptions object"))]
|
|
||||||
public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
|
public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/System/Configuration/MetadataPlugins", "GET")]
|
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
|
||||||
[Api(("Gets all available metadata plugins"))]
|
|
||||||
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
|
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/System/Configuration/VideoImageExtraction", "POST")]
|
[Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")]
|
||||||
[Api(("Updates image extraction for all types"))]
|
|
||||||
public class UpdateVideoImageExtraction : IReturnVoid
|
public class UpdateVideoImageExtraction : IReturnVoid
|
||||||
{
|
{
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
|
|
|
@ -12,8 +12,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class UpdateDisplayPreferences
|
/// Class UpdateDisplayPreferences
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/DisplayPreferences/{DisplayPreferencesId}", "POST")]
|
[Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")]
|
||||||
[Api(("Updates a user's display preferences for an item"))]
|
|
||||||
public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
|
public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -30,8 +29,7 @@ namespace MediaBrowser.Api
|
||||||
public string Client { get; set; }
|
public string Client { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/DisplayPreferences/{Id}", "GET")]
|
[Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]
|
||||||
[Api(("Gets a user's display preferences for an item"))]
|
|
||||||
public class GetDisplayPreferences : IReturn<DisplayPreferences>
|
public class GetDisplayPreferences : IReturn<DisplayPreferences>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
90
MediaBrowser.Api/DlnaService.cs
Normal file
90
MediaBrowser.Api/DlnaService.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,8 +13,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetDirectoryContents
|
/// Class GetDirectoryContents
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Environment/DirectoryContents", "GET")]
|
[Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")]
|
||||||
[Api(Description = "Gets the contents of a given directory in the file system")]
|
|
||||||
public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
|
public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -46,8 +45,7 @@ namespace MediaBrowser.Api
|
||||||
public bool IncludeHidden { get; set; }
|
public bool IncludeHidden { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Environment/NetworkShares", "GET")]
|
[Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
|
||||||
[Api(Description = "Gets shares from a network device")]
|
|
||||||
public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
|
public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -61,8 +59,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetDrives
|
/// Class GetDrives
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Environment/Drives", "GET")]
|
[Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")]
|
||||||
[Api(Description = "Gets available drives from the server's file system")]
|
|
||||||
public class GetDrives : IReturn<List<FileSystemEntryInfo>>
|
public class GetDrives : IReturn<List<FileSystemEntryInfo>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -70,14 +67,12 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetNetworkComputers
|
/// Class GetNetworkComputers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Environment/NetworkDevices", "GET")]
|
[Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")]
|
||||||
[Api(Description = "Gets a list of devices on the network")]
|
|
||||||
public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
|
public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Environment/ParentPath", "GET")]
|
[Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")]
|
||||||
[Api(Description = "Gets the parent path of a given path")]
|
|
||||||
public class GetParentPath : IReturn<string>
|
public class GetParentPath : IReturn<string>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Globalization;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Dto;
|
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
@ -7,6 +6,7 @@ using MediaBrowser.Model.Dto;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetSimilarGames
|
/// Class GetSimilarGames
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Games/{Id}/Similar", "GET")]
|
[Route("/Games/{Id}/Similar", "GET", Summary = "Finds games similar to a given game.")]
|
||||||
[Api(Description = "Finds games similar to a given game.")]
|
|
||||||
public class GetSimilarGames : BaseGetSimilarItemsFromItem
|
public class GetSimilarGames : BaseGetSimilarItemsFromItem
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -24,8 +23,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetGameSystemSummaries
|
/// Class GetGameSystemSummaries
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Games/SystemSummaries", "GET")]
|
[Route("/Games/SystemSummaries", "GET", Summary = "Finds games similar to a given game.")]
|
||||||
[Api(Description = "Finds games similar to a given game.")]
|
|
||||||
public class GetGameSystemSummaries : IReturn<List<GameSystemSummary>>
|
public class GetGameSystemSummaries : IReturn<List<GameSystemSummary>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -39,8 +37,7 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetGameSystemSummaries
|
/// Class GetGameSystemSummaries
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Games/PlayerIndex", "GET")]
|
[Route("/Games/PlayerIndex", "GET", Summary = "Gets an index of players (1-x) and the number of games listed under each")]
|
||||||
[Api(Description = "Gets an index of players (1-x) and the number of games listed under each")]
|
|
||||||
public class GetPlayerIndex : IReturn<List<ItemIndex>>
|
public class GetPlayerIndex : IReturn<List<ItemIndex>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -117,7 +114,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public object Get(GetPlayerIndex request)
|
public object Get(GetPlayerIndex request)
|
||||||
{
|
{
|
||||||
var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager)
|
var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager)
|
||||||
|
|
|
@ -15,7 +15,6 @@ using ServiceStack.Text.Controller;
|
||||||
using ServiceStack.Web;
|
using ServiceStack.Web;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
@ -776,15 +775,6 @@ namespace MediaBrowser.Api.Images
|
||||||
|
|
||||||
var bytes = Convert.FromBase64String(text);
|
var bytes = Convert.FromBase64String(text);
|
||||||
|
|
||||||
// Validate first
|
|
||||||
using (var validationStream = new MemoryStream(bytes))
|
|
||||||
{
|
|
||||||
// This will throw an exception if it's not a valid image
|
|
||||||
using (Image.FromStream(validationStream))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var memoryStream = new MemoryStream(bytes)
|
var memoryStream = new MemoryStream(bytes)
|
||||||
{
|
{
|
||||||
Position = 0
|
Position = 0
|
||||||
|
|
|
@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Channels;
|
using MediaBrowser.Model.Channels;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -245,12 +246,13 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
|
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
|
||||||
IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager)
|
IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager, ISessionManager sessionManager)
|
||||||
{
|
{
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
@ -258,6 +260,7 @@ namespace MediaBrowser.Api.Library
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
|
_sessionManager = sessionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetMediaFolders request)
|
public object Get(GetMediaFolders request)
|
||||||
|
@ -504,6 +507,13 @@ namespace MediaBrowser.Api.Library
|
||||||
{
|
{
|
||||||
var item = _dtoService.GetItemByDtoId(request.Id);
|
var item = _dtoService.GetItemByDtoId(request.Id);
|
||||||
|
|
||||||
|
var session = GetSession(_sessionManager);
|
||||||
|
|
||||||
|
if (!session.UserId.HasValue || !_userManager.GetUserById(session.UserId.Value).Configuration.EnableContentDeletion)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException("This operation requires a logged in user with delete access.");
|
||||||
|
}
|
||||||
|
|
||||||
return _libraryManager.DeleteItem(item);
|
return _libraryManager.DeleteItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,12 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.LiveTv
|
namespace MediaBrowser.Api.LiveTv
|
||||||
{
|
{
|
||||||
[Route("/LiveTv/Info", "GET")]
|
[Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
|
||||||
[Api(Description = "Gets available live tv services.")]
|
|
||||||
public class GetLiveTvInfo : IReturn<LiveTvInfo>
|
public class GetLiveTvInfo : IReturn<LiveTvInfo>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Channels", "GET")]
|
[Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
|
||||||
[Api(Description = "Gets available live tv channels.")]
|
|
||||||
public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>
|
public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -43,8 +41,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public int? Limit { get; set; }
|
public int? Limit { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Channels/{Id}", "GET")]
|
[Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
|
||||||
[Api(Description = "Gets a live tv channel")]
|
|
||||||
public class GetChannel : IReturn<ChannelInfoDto>
|
public class GetChannel : IReturn<ChannelInfoDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -58,8 +55,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings", "GET")]
|
[Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
|
||||||
[Api(Description = "Gets live tv recordings")]
|
|
||||||
public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
|
public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -87,16 +83,14 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/Groups", "GET")]
|
[Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
|
||||||
[Api(Description = "Gets live tv recording groups")]
|
|
||||||
public class GetRecordingGroups : IReturn<QueryResult<RecordingGroupDto>>
|
public class GetRecordingGroups : IReturn<QueryResult<RecordingGroupDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/{Id}", "GET")]
|
[Route("/LiveTv/Recordings/{Id}", "GET", Summary = "Gets a live tv recording")]
|
||||||
[Api(Description = "Gets a live tv recording")]
|
|
||||||
public class GetRecording : IReturn<RecordingInfoDto>
|
public class GetRecording : IReturn<RecordingInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
@ -106,32 +100,28 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Tuners/{Id}/Reset", "POST")]
|
[Route("/LiveTv/Tuners/{Id}/Reset", "POST", Summary = "Resets a tv tuner")]
|
||||||
[Api(Description = "Resets a tv tuner")]
|
|
||||||
public class ResetTuner : IReturnVoid
|
public class ResetTuner : IReturnVoid
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Tuner Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Tuner Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers/{Id}", "GET")]
|
[Route("/LiveTv/Timers/{Id}", "GET", Summary = "Gets a live tv timer")]
|
||||||
[Api(Description = "Gets a live tv timer")]
|
|
||||||
public class GetTimer : IReturn<TimerInfoDto>
|
public class GetTimer : IReturn<TimerInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers/Defaults", "GET")]
|
[Route("/LiveTv/Timers/Defaults", "GET", Summary = "Gets default values for a new timer")]
|
||||||
[Api(Description = "Gets default values for a new timer")]
|
|
||||||
public class GetDefaultTimer : IReturn<SeriesTimerInfoDto>
|
public class GetDefaultTimer : IReturn<SeriesTimerInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ProgramId", Description = "Optional, to attach default values based on a program.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ProgramId", Description = "Optional, to attach default values based on a program.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ProgramId { get; set; }
|
public string ProgramId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers", "GET")]
|
[Route("/LiveTv/Timers", "GET", Summary = "Gets live tv timers")]
|
||||||
[Api(Description = "Gets live tv timers")]
|
|
||||||
public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
|
public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -141,8 +131,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs", "GET,POST")]
|
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
||||||
[Api(Description = "Gets available live tv epgs..")]
|
|
||||||
public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
|
public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
@ -164,8 +153,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string MaxEndDate { get; set; }
|
public string MaxEndDate { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs/Recommended", "GET")]
|
[Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
|
||||||
[Api(Description = "Gets available live tv epgs..")]
|
|
||||||
public class GetRecommendedPrograms : IReturn<QueryResult<ProgramInfoDto>>
|
public class GetRecommendedPrograms : IReturn<QueryResult<ProgramInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
@ -181,8 +169,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public bool? HasAired { get; set; }
|
public bool? HasAired { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs/{Id}", "GET")]
|
[Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
|
||||||
[Api(Description = "Gets a live tv program")]
|
|
||||||
public class GetProgram : IReturn<ProgramInfoDto>
|
public class GetProgram : IReturn<ProgramInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
@ -193,44 +180,38 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/{Id}", "DELETE")]
|
[Route("/LiveTv/Recordings/{Id}", "DELETE", Summary = "Deletes a live tv recording")]
|
||||||
[Api(Description = "Deletes a live tv recording")]
|
|
||||||
public class DeleteRecording : IReturnVoid
|
public class DeleteRecording : IReturnVoid
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers/{Id}", "DELETE")]
|
[Route("/LiveTv/Timers/{Id}", "DELETE", Summary = "Cancels a live tv timer")]
|
||||||
[Api(Description = "Cancels a live tv timer")]
|
|
||||||
public class CancelTimer : IReturnVoid
|
public class CancelTimer : IReturnVoid
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers/{Id}", "POST")]
|
[Route("/LiveTv/Timers/{Id}", "POST", Summary = "Updates a live tv timer")]
|
||||||
[Api(Description = "Updates a live tv timer")]
|
|
||||||
public class UpdateTimer : TimerInfoDto, IReturnVoid
|
public class UpdateTimer : TimerInfoDto, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Timers", "POST")]
|
[Route("/LiveTv/Timers", "POST", Summary = "Creates a live tv timer")]
|
||||||
[Api(Description = "Creates a live tv timer")]
|
|
||||||
public class CreateTimer : TimerInfoDto, IReturnVoid
|
public class CreateTimer : TimerInfoDto, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/SeriesTimers/{Id}", "GET")]
|
[Route("/LiveTv/SeriesTimers/{Id}", "GET", Summary = "Gets a live tv series timer")]
|
||||||
[Api(Description = "Gets a live tv series timer")]
|
|
||||||
public class GetSeriesTimer : IReturn<TimerInfoDto>
|
public class GetSeriesTimer : IReturn<TimerInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/SeriesTimers", "GET")]
|
[Route("/LiveTv/SeriesTimers", "GET", Summary = "Gets live tv series timers")]
|
||||||
[Api(Description = "Gets live tv series timers")]
|
|
||||||
public class GetSeriesTimers : IReturn<QueryResult<SeriesTimerInfoDto>>
|
public class GetSeriesTimers : IReturn<QueryResult<SeriesTimerInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "SortBy", Description = "Optional. Sort by SortName or Priority", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "SortBy", Description = "Optional. Sort by SortName or Priority", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
@ -240,36 +221,31 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public SortOrder SortOrder { get; set; }
|
public SortOrder SortOrder { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/SeriesTimers/{Id}", "DELETE")]
|
[Route("/LiveTv/SeriesTimers/{Id}", "DELETE", Summary = "Cancels a live tv series timer")]
|
||||||
[Api(Description = "Cancels a live tv series timer")]
|
|
||||||
public class CancelSeriesTimer : IReturnVoid
|
public class CancelSeriesTimer : IReturnVoid
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/SeriesTimers/{Id}", "POST")]
|
[Route("/LiveTv/SeriesTimers/{Id}", "POST", Summary = "Updates a live tv series timer")]
|
||||||
[Api(Description = "Updates a live tv series timer")]
|
|
||||||
public class UpdateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
|
public class UpdateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/SeriesTimers", "POST")]
|
[Route("/LiveTv/SeriesTimers", "POST", Summary = "Creates a live tv series timer")]
|
||||||
[Api(Description = "Creates a live tv series timer")]
|
|
||||||
public class CreateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
|
public class CreateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/Groups/{Id}", "GET")]
|
[Route("/LiveTv/Recordings/Groups/{Id}", "GET", Summary = "Gets a recording group")]
|
||||||
[Api(Description = "Gets a recording group")]
|
|
||||||
public class GetRecordingGroup : IReturn<RecordingGroupDto>
|
public class GetRecordingGroup : IReturn<RecordingGroupDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Id", Description = "Recording group Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Recording group Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/GuideInfo", "GET")]
|
[Route("/LiveTv/GuideInfo", "GET", Summary = "Gets guide info")]
|
||||||
[Api(Description = "Gets guide info")]
|
|
||||||
public class GetGuideInfo : IReturn<GuideInfo>
|
public class GetGuideInfo : IReturn<GuideInfo>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ServiceStack.Interfaces">
|
<Reference Include="ServiceStack.Interfaces">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||||
|
@ -67,6 +66,7 @@
|
||||||
<Link>Properties\SharedVersion.cs</Link>
|
<Link>Properties\SharedVersion.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="ChannelService.cs" />
|
<Compile Include="ChannelService.cs" />
|
||||||
|
<Compile Include="DlnaService.cs" />
|
||||||
<Compile Include="Movies\CollectionService.cs" />
|
<Compile Include="Movies\CollectionService.cs" />
|
||||||
<Compile Include="Music\AlbumsService.cs" />
|
<Compile Include="Music\AlbumsService.cs" />
|
||||||
<Compile Include="AppThemeService.cs" />
|
<Compile Include="AppThemeService.cs" />
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace MediaBrowser.Api.Movies
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetSimilarMovies
|
/// Class GetSimilarMovies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Movies/{Id}/Similar", "GET")]
|
[Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
|
||||||
[Api(Description = "Finds movies and trailers similar to a given movie.")]
|
|
||||||
public class GetSimilarMovies : BaseGetSimilarItemsFromItem
|
public class GetSimilarMovies : BaseGetSimilarItemsFromItem
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "IncludeTrailers", Description = "Whether or not to include trailers within the results. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IncludeTrailers", Description = "Whether or not to include trailers within the results. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -30,8 +29,7 @@ namespace MediaBrowser.Api.Movies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Movies/Recommendations", "GET")]
|
[Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
|
||||||
[Api(Description = "Gets movie recommendations")]
|
|
||||||
public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
|
public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
|
|
@ -10,8 +10,7 @@ namespace MediaBrowser.Api.Movies
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetSimilarTrailers
|
/// Class GetSimilarTrailers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Trailers/{Id}/Similar", "GET")]
|
[Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
||||||
[Api(Description = "Finds movies and trailers similar to a given trailer.")]
|
|
||||||
public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
|
public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,28 +9,24 @@ using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Music
|
namespace MediaBrowser.Api.Music
|
||||||
{
|
{
|
||||||
[Route("/Songs/{Id}/InstantMix", "GET")]
|
[Route("/Songs/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given song")]
|
||||||
[Api(Description = "Creates an instant playlist based on a given song")]
|
|
||||||
public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
|
public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Albums/{Id}/InstantMix", "GET")]
|
[Route("/Albums/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given album")]
|
||||||
[Api(Description = "Creates an instant playlist based on a given album")]
|
|
||||||
public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
|
public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Artists/{Name}/InstantMix", "GET")]
|
[Route("/Artists/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
|
||||||
[Api(Description = "Creates an instant playlist based on a given artist")]
|
|
||||||
public class GetInstantMixFromArtist : BaseGetSimilarItems
|
public class GetInstantMixFromArtist : BaseGetSimilarItems
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/MusicGenres/{Name}/InstantMix", "GET")]
|
[Route("/MusicGenres/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
|
||||||
[Api(Description = "Creates an instant playlist based on a music genre")]
|
|
||||||
public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
|
public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
@ -65,6 +66,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
protected IItemRepository ItemRepository { get; private set; }
|
protected IItemRepository ItemRepository { get; private set; }
|
||||||
protected ILiveTvManager LiveTvManager { get; private set; }
|
protected ILiveTvManager LiveTvManager { get; private set; }
|
||||||
|
protected IDlnaManager DlnaManager { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
|
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
|
||||||
|
@ -77,8 +79,9 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// <param name="dtoService">The dto service.</param>
|
/// <param name="dtoService">The dto service.</param>
|
||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="itemRepository">The item repository.</param>
|
/// <param name="itemRepository">The item repository.</param>
|
||||||
protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager)
|
protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
|
||||||
{
|
{
|
||||||
|
DlnaManager = dlnaManager;
|
||||||
EncodingManager = encodingManager;
|
EncodingManager = encodingManager;
|
||||||
LiveTvManager = liveTvManager;
|
LiveTvManager = liveTvManager;
|
||||||
ItemRepository = itemRepository;
|
ItemRepository = itemRepository;
|
||||||
|
@ -313,6 +316,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <param name="videoCodec">The video codec.</param>
|
/// <param name="videoCodec">The video codec.</param>
|
||||||
|
/// <param name="isHls">if set to <c>true</c> [is HLS].</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
|
protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
|
||||||
{
|
{
|
||||||
|
@ -337,20 +341,17 @@ namespace MediaBrowser.Api.Playback
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isHls)
|
switch (qualitySetting)
|
||||||
{
|
{
|
||||||
switch (qualitySetting)
|
case EncodingQuality.HighSpeed:
|
||||||
{
|
param += " -crf 23";
|
||||||
case EncodingQuality.HighSpeed:
|
break;
|
||||||
param += " -crf 23";
|
case EncodingQuality.HighQuality:
|
||||||
break;
|
param += " -crf 20";
|
||||||
case EncodingQuality.HighQuality:
|
break;
|
||||||
param += " -crf 20";
|
case EncodingQuality.MaxQuality:
|
||||||
break;
|
param += " -crf 18";
|
||||||
case EncodingQuality.MaxQuality:
|
break;
|
||||||
param += " -crf 18";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,14 +503,13 @@ namespace MediaBrowser.Api.Playback
|
||||||
return string.Format("{4} -vf \"{0}scale=trunc({1}/2)*2:trunc({2}/2)*2{3}\"", yadifParam, widthParam, heightParam, assSubtitleParam, copyTsParam);
|
return string.Format("{4} -vf \"{0}scale=trunc({1}/2)*2:trunc({2}/2)*2{3}\"", yadifParam, widthParam, heightParam, assSubtitleParam, copyTsParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Max dimensions were supplied
|
// If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
|
||||||
//this makes my brain hurt. For width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
|
|
||||||
if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
|
if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
|
||||||
{
|
{
|
||||||
var MaxwidthParam = request.MaxWidth.Value.ToString(UsCulture);
|
var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
|
||||||
var MaxheightParam = request.MaxHeight.Value.ToString(UsCulture);
|
var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
|
||||||
|
|
||||||
return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, MaxwidthParam, MaxheightParam, assSubtitleParam, copyTsParam);
|
return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, maxWidthParam, maxHeightParam, assSubtitleParam, copyTsParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
|
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
|
||||||
|
@ -774,29 +774,24 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
var codec = request.AudioCodec;
|
var codec = request.AudioCodec;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
|
return "aac -strict experimental";
|
||||||
{
|
}
|
||||||
return "aac -strict experimental";
|
if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
|
||||||
}
|
{
|
||||||
if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
|
return "libmp3lame";
|
||||||
{
|
}
|
||||||
return "libmp3lame";
|
if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
|
||||||
}
|
{
|
||||||
if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
|
return "libvorbis";
|
||||||
{
|
}
|
||||||
return "libvorbis";
|
if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
|
||||||
}
|
{
|
||||||
if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
|
return "wmav2";
|
||||||
{
|
|
||||||
return "wmav2";
|
|
||||||
}
|
|
||||||
|
|
||||||
return codec.ToLower();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "copy";
|
return codec.ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -972,8 +967,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
private async void StreamToStandardInput(Process process, StreamState state)
|
private async void StreamToStandardInput(Process process, StreamState state)
|
||||||
{
|
{
|
||||||
state.StandardInputCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await StreamToStandardInputInternal(process, state).ConfigureAwait(false);
|
await StreamToStandardInputInternal(process, state).ConfigureAwait(false);
|
||||||
|
@ -1034,11 +1027,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
var hasFixedResolution = state.VideoRequest.HasFixedResolution;
|
var hasFixedResolution = state.VideoRequest.HasFixedResolution;
|
||||||
|
|
||||||
if (isHls)
|
|
||||||
{
|
|
||||||
return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (hasFixedResolution)
|
if (hasFixedResolution)
|
||||||
|
@ -1049,7 +1037,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
// With vpx when crf is used, b:v becomes a max rate
|
// With vpx when crf is used, b:v becomes a max rate
|
||||||
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide
|
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide
|
||||||
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
||||||
//return string.Format(" -minrate:v ({0}*.95) -maxrate:v ({0}*1.05) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -1057,13 +1044,17 @@ namespace MediaBrowser.Api.Playback
|
||||||
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// H264
|
// H264
|
||||||
if (hasFixedResolution)
|
if (hasFixedResolution)
|
||||||
{
|
{
|
||||||
|
if (isHls)
|
||||||
|
{
|
||||||
|
return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
|
||||||
|
}
|
||||||
|
|
||||||
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format(" -maxrate {0} -bufsize {1}",
|
return string.Format(" -maxrate {0} -bufsize {1}",
|
||||||
bitrate.Value.ToString(UsCulture),
|
bitrate.Value.ToString(UsCulture),
|
||||||
(bitrate.Value * 2).ToString(UsCulture));
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
|
@ -1212,7 +1203,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
// Device profile name
|
request.DeviceProfileId = val;
|
||||||
}
|
}
|
||||||
else if (i == 1)
|
else if (i == 1)
|
||||||
{
|
{
|
||||||
|
@ -1270,35 +1261,35 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
videoRequest.MaxWidth = int.Parse(val, UsCulture);
|
videoRequest.MaxFramerate = double.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 12)
|
else if (i == 12)
|
||||||
{
|
{
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
videoRequest.MaxHeight = int.Parse(val, UsCulture);
|
videoRequest.MaxWidth = int.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 13)
|
else if (i == 13)
|
||||||
{
|
{
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
videoRequest.Framerate = int.Parse(val, UsCulture);
|
videoRequest.MaxHeight = int.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 14)
|
else if (i == 14)
|
||||||
{
|
{
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
request.StartTimeTicks = long.Parse(val, UsCulture);
|
videoRequest.Framerate = int.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 15)
|
else if (i == 15)
|
||||||
{
|
{
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
videoRequest.Profile = val;
|
request.StartTimeTicks = long.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 16)
|
else if (i == 16)
|
||||||
|
@ -1487,9 +1478,181 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
|
state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
|
||||||
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
|
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
|
||||||
|
|
||||||
|
ApplyDeviceProfileSettings(state);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyDeviceProfileSettings(StreamState state)
|
||||||
|
{
|
||||||
|
var headers = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
foreach (var key in Request.Headers.AllKeys)
|
||||||
|
{
|
||||||
|
headers[key] = Request.Headers[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var profile = string.IsNullOrWhiteSpace(state.Request.DeviceProfileId) ?
|
||||||
|
DlnaManager.GetProfile(headers) :
|
||||||
|
DlnaManager.GetProfile(state.Request.DeviceProfileId);
|
||||||
|
|
||||||
|
if (profile == null)
|
||||||
|
{
|
||||||
|
// Don't use settings from the default profile.
|
||||||
|
// Only use a specific profile if it was requested.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var container = Path.GetExtension(state.RequestedUrl);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(container))
|
||||||
|
{
|
||||||
|
container = Path.GetExtension(GetOutputFilePath(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
var audioCodec = state.Request.AudioCodec;
|
||||||
|
|
||||||
|
if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.AudioStream != null)
|
||||||
|
{
|
||||||
|
audioCodec = state.AudioStream.Codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoCodec = state.VideoRequest == null ? null : state.VideoRequest.VideoCodec;
|
||||||
|
|
||||||
|
if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.VideoStream != null)
|
||||||
|
{
|
||||||
|
videoCodec = state.VideoStream.Codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaProfile = state.VideoRequest == null ?
|
||||||
|
profile.GetAudioMediaProfile(container, audioCodec, state.AudioStream) :
|
||||||
|
profile.GetVideoMediaProfile(container, audioCodec, videoCodec, state.AudioStream, state.VideoStream);
|
||||||
|
|
||||||
|
if (mediaProfile != null)
|
||||||
|
{
|
||||||
|
state.MimeType = mediaProfile.MimeType;
|
||||||
|
state.OrgPn = mediaProfile.OrgPn;
|
||||||
|
}
|
||||||
|
|
||||||
|
var transcodingProfile = state.VideoRequest == null ?
|
||||||
|
profile.GetAudioTranscodingProfile(container, audioCodec) :
|
||||||
|
profile.GetVideoTranscodingProfile(container, audioCodec, videoCodec);
|
||||||
|
|
||||||
|
if (transcodingProfile != null)
|
||||||
|
{
|
||||||
|
state.EstimateContentLength = transcodingProfile.EstimateContentLength;
|
||||||
|
state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
|
||||||
|
state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
|
||||||
|
|
||||||
|
foreach (var setting in transcodingProfile.Settings)
|
||||||
|
{
|
||||||
|
switch (setting.Name)
|
||||||
|
{
|
||||||
|
case TranscodingSettingType.VideoProfile:
|
||||||
|
{
|
||||||
|
if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile))
|
||||||
|
{
|
||||||
|
state.VideoRequest.Profile = setting.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unrecognized TranscodingSettingType");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the dlna headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">The state.</param>
|
||||||
|
/// <param name="responseHeaders">The response headers.</param>
|
||||||
|
/// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param>
|
||||||
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||||
|
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
|
||||||
|
{
|
||||||
|
var timeSeek = GetHeader("TimeSeekRange.dlna.org");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(timeSeek))
|
||||||
|
{
|
||||||
|
ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var transferMode = GetHeader("transferMode.dlna.org");
|
||||||
|
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
|
||||||
|
responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
|
||||||
|
|
||||||
|
var contentFeatures = string.Empty;
|
||||||
|
var extension = GetOutputFileExtension(state);
|
||||||
|
|
||||||
|
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
|
||||||
|
var orgOp = isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00";
|
||||||
|
|
||||||
|
// 0 = native, 1 = transcoded
|
||||||
|
var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
|
||||||
|
|
||||||
|
const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(state.OrgPn))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=" + state.OrgPn;
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=MP3";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=AAC_ISO";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=WMABASE";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=AVI";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=MATROSKA";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
||||||
|
}
|
||||||
|
else if (string.Equals(extension, ".ts", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
||||||
|
}
|
||||||
|
//else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
|
||||||
|
//{
|
||||||
|
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
||||||
|
//}
|
||||||
|
//else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
|
||||||
|
//{
|
||||||
|
// // ??
|
||||||
|
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(contentFeatures))
|
||||||
|
{
|
||||||
|
responseHeaders["contentFeatures.dlna.org"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in responseHeaders)
|
||||||
|
{
|
||||||
|
Request.Response.AddHeader(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enforces the resolution limit.
|
/// Enforces the resolution limit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1605,7 +1768,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
return "vorbis";
|
return "vorbis";
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return "copy";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseHlsService : BaseStreamingService
|
public abstract class BaseHlsService : BaseStreamingService
|
||||||
{
|
{
|
||||||
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
|
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
builder.AppendLine("#EXTM3U");
|
builder.AppendLine("#EXTM3U");
|
||||||
|
|
||||||
// Pad a little to satisfy the apple hls validator
|
// Pad a little to satisfy the apple hls validator
|
||||||
var paddedBitrate = Convert.ToInt32(bitrate * 1.05);
|
var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
|
||||||
|
|
||||||
// Main stream
|
// Main stream
|
||||||
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
|
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
|
@ -60,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
public class DynamicHlsService : BaseHlsService
|
public class DynamicHlsService : BaseHlsService
|
||||||
{
|
{
|
||||||
public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
|
public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
@ -52,7 +53,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VideoHlsService : BaseHlsService
|
public class VideoHlsService : BaseHlsService
|
||||||
{
|
{
|
||||||
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
|
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
@ -16,23 +17,22 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetAudioStream
|
/// Class GetAudioStream
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Audio/{Id}/stream.mp3", "GET")]
|
[Route("/Audio/{Id}/stream.mp3", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.wma", "GET")]
|
[Route("/Audio/{Id}/stream.wma", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.aac", "GET")]
|
[Route("/Audio/{Id}/stream.aac", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.flac", "GET")]
|
[Route("/Audio/{Id}/stream.flac", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.ogg", "GET")]
|
[Route("/Audio/{Id}/stream.ogg", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.oga", "GET")]
|
[Route("/Audio/{Id}/stream.oga", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.webm", "GET")]
|
[Route("/Audio/{Id}/stream.webm", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream", "GET")]
|
[Route("/Audio/{Id}/stream", "GET", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.mp3", "HEAD")]
|
[Route("/Audio/{Id}/stream.mp3", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.wma", "HEAD")]
|
[Route("/Audio/{Id}/stream.wma", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.aac", "HEAD")]
|
[Route("/Audio/{Id}/stream.aac", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.flac", "HEAD")]
|
[Route("/Audio/{Id}/stream.flac", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.ogg", "HEAD")]
|
[Route("/Audio/{Id}/stream.ogg", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.oga", "HEAD")]
|
[Route("/Audio/{Id}/stream.oga", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream.webm", "HEAD")]
|
[Route("/Audio/{Id}/stream.webm", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Route("/Audio/{Id}/stream", "HEAD")]
|
[Route("/Audio/{Id}/stream", "HEAD", Summary = "Gets an audio stream")]
|
||||||
[Api(Description = "Gets an audio stream")]
|
|
||||||
public class GetAudioStream : StreamRequest
|
public class GetAudioStream : StreamRequest
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AudioService : BaseProgressiveStreamingService
|
public class AudioService : BaseProgressiveStreamingService
|
||||||
{
|
{
|
||||||
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, httpClient, imageProcessor)
|
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
|
||||||
|
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using ServiceStack.Web;
|
using ServiceStack.Web;
|
||||||
using System;
|
using System;
|
||||||
|
@ -26,8 +26,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
protected readonly IImageProcessor ImageProcessor;
|
protected readonly IImageProcessor ImageProcessor;
|
||||||
protected readonly IHttpClient HttpClient;
|
protected readonly IHttpClient HttpClient;
|
||||||
|
|
||||||
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor)
|
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
|
||||||
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager)
|
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||||
{
|
{
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
ImageProcessor = imageProcessor;
|
ImageProcessor = imageProcessor;
|
||||||
|
@ -100,92 +100,6 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds the dlna headers.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="state">The state.</param>
|
|
||||||
/// <param name="responseHeaders">The response headers.</param>
|
|
||||||
/// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param>
|
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
|
||||||
private void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
|
|
||||||
{
|
|
||||||
var timeSeek = GetHeader("TimeSeekRange.dlna.org");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(timeSeek))
|
|
||||||
{
|
|
||||||
ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var transferMode = GetHeader("transferMode.dlna.org");
|
|
||||||
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
|
|
||||||
responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
|
|
||||||
|
|
||||||
var contentFeatures = string.Empty;
|
|
||||||
var extension = GetOutputFileExtension(state);
|
|
||||||
|
|
||||||
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
|
|
||||||
var orgOp = isStaticallyStreamed ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00";
|
|
||||||
|
|
||||||
// 0 = native, 1 = transcoded
|
|
||||||
var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
|
|
||||||
|
|
||||||
const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
|
|
||||||
|
|
||||||
if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=MP3";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=AAC_ISO";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=WMABASE";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=AVI";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=MATROSKA";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
|
||||||
}
|
|
||||||
else if (string.Equals(extension, ".ts", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
|
||||||
}
|
|
||||||
//else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
|
|
||||||
//{
|
|
||||||
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
|
||||||
//}
|
|
||||||
//else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
|
|
||||||
//{
|
|
||||||
// // ??
|
|
||||||
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(contentFeatures))
|
|
||||||
{
|
|
||||||
responseHeaders["contentFeatures.dlna.org"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in responseHeaders)
|
|
||||||
{
|
|
||||||
Request.Response.AddHeader(item.Key, item.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the transcoding job.
|
/// Gets the type of the transcoding job.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -303,18 +217,30 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
|
|
||||||
var contentType = state.GetMimeType(outputPath);
|
var contentType = state.GetMimeType(outputPath);
|
||||||
|
|
||||||
|
var contentLength = state.EstimateContentLength ? GetEstimatedContentLength(state) : null;
|
||||||
|
|
||||||
|
if (contentLength.HasValue)
|
||||||
|
{
|
||||||
|
responseHeaders["Content-Length"] = contentLength.Value.ToString(UsCulture);
|
||||||
|
}
|
||||||
|
|
||||||
// Headers only
|
// Headers only
|
||||||
if (isHeadRequest)
|
if (isHeadRequest)
|
||||||
{
|
{
|
||||||
var streamResult = ResultFactory.GetResult(new byte[] { }, contentType, responseHeaders);
|
var streamResult = ResultFactory.GetResult(new byte[] { }, contentType, responseHeaders);
|
||||||
var hasOptions = streamResult as IHasOptions;
|
|
||||||
if (hasOptions != null)
|
if (!contentLength.HasValue)
|
||||||
{
|
{
|
||||||
if (hasOptions.Options.ContainsKey("Content-Length"))
|
var hasOptions = streamResult as IHasOptions;
|
||||||
|
if (hasOptions != null)
|
||||||
{
|
{
|
||||||
hasOptions.Options.Remove("Content-Length");
|
if (hasOptions.Options.ContainsKey("Content-Length"))
|
||||||
|
{
|
||||||
|
hasOptions.Options.Remove("Content-Length");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamResult;
|
return streamResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,5 +265,31 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the estimated content.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">The state.</param>
|
||||||
|
/// <returns>System.Nullable{System.Int64}.</returns>
|
||||||
|
private long? GetEstimatedContentLength(StreamState state)
|
||||||
|
{
|
||||||
|
var totalBitrate = 0;
|
||||||
|
|
||||||
|
if (state.Request.AudioBitRate.HasValue)
|
||||||
|
{
|
||||||
|
totalBitrate += state.Request.AudioBitRate.Value;
|
||||||
|
}
|
||||||
|
if (state.VideoRequest != null && state.VideoRequest.VideoBitRate.HasValue)
|
||||||
|
{
|
||||||
|
totalBitrate += state.VideoRequest.VideoBitRate.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalBitrate > 0 && state.RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
return Convert.ToInt64(totalBitrate * TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
@ -58,7 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VideoService : BaseProgressiveStreamingService
|
public class VideoService : BaseProgressiveStreamingService
|
||||||
{
|
{
|
||||||
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, httpClient, imageProcessor)
|
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +138,11 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
|
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.EnableMpegtsM2TsMode)
|
||||||
|
{
|
||||||
|
args += " -mpegts_m2ts_mode 1";
|
||||||
|
}
|
||||||
|
|
||||||
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
||||||
|
|
||||||
args += keyFrameArg;
|
args += keyFrameArg;
|
||||||
|
|
|
@ -65,6 +65,9 @@ namespace MediaBrowser.Api.Playback
|
||||||
[ApiMember(Name = "Static", Description = "Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Static", Description = "Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool Static { get; set; }
|
public bool Static { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "DeviceProfileId", Description = "Optional. The dlna device profile id to utilize.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string DeviceProfileId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For testing purposes
|
/// For testing purposes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -77,8 +78,21 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public string InputAudioCodec { get; set; }
|
public string InputAudioCodec { get; set; }
|
||||||
|
|
||||||
|
public string MimeType { get; set; }
|
||||||
|
public string OrgPn { get; set; }
|
||||||
|
|
||||||
|
// DLNA Settings
|
||||||
|
public bool EstimateContentLength { get; set; }
|
||||||
|
public bool EnableMpegtsM2TsMode { get; set; }
|
||||||
|
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
||||||
|
|
||||||
public string GetMimeType(string outputPath)
|
public string GetMimeType(string outputPath)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(MimeType))
|
||||||
|
{
|
||||||
|
return MimeType;
|
||||||
|
}
|
||||||
|
|
||||||
return MimeTypes.GetMimeType(outputPath);
|
return MimeTypes.GetMimeType(outputPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
using MediaBrowser.Common.ScheduledTasks;
|
using MediaBrowser.Common.ScheduledTasks;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
|
using ServiceStack.Text.Controller;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ServiceStack.Text.Controller;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.ScheduledTasks
|
namespace MediaBrowser.Api.ScheduledTasks
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetScheduledTask
|
/// Class GetScheduledTask
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks/{Id}", "GET")]
|
[Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
|
||||||
[Api(Description = "Gets a scheduled task, by Id")]
|
|
||||||
public class GetScheduledTask : IReturn<TaskInfo>
|
public class GetScheduledTask : IReturn<TaskInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,8 +26,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetScheduledTasks
|
/// Class GetScheduledTasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks", "GET")]
|
[Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
|
||||||
[Api(Description = "Gets scheduled tasks")]
|
|
||||||
public class GetScheduledTasks : IReturn<List<TaskInfo>>
|
public class GetScheduledTasks : IReturn<List<TaskInfo>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -38,8 +36,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class StartScheduledTask
|
/// Class StartScheduledTask
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks/Running/{Id}", "POST")]
|
[Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
|
||||||
[Api(Description = "Starts a scheduled task")]
|
|
||||||
public class StartScheduledTask : IReturnVoid
|
public class StartScheduledTask : IReturnVoid
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -53,8 +50,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class StopScheduledTask
|
/// Class StopScheduledTask
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks/Running/{Id}", "DELETE")]
|
[Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
|
||||||
[Api(Description = "Stops a scheduled task")]
|
|
||||||
public class StopScheduledTask : IReturnVoid
|
public class StopScheduledTask : IReturnVoid
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -68,8 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class UpdateScheduledTaskTriggers
|
/// Class UpdateScheduledTaskTriggers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks/{Id}/Triggers", "POST")]
|
[Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
|
||||||
[Api(Description = "Updates the triggers for a scheduled task")]
|
|
||||||
public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
|
public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -20,9 +20,8 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetItems
|
/// Class GetItems
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Items", "GET")]
|
[Route("/Items", "GET", Summary = "Gets items based on a query.")]
|
||||||
[Route("/Users/{UserId}/Items", "GET")]
|
[Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
|
||||||
[Api(Description = "Gets items based on a query.")]
|
|
||||||
public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
|
public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -8,15 +8,13 @@ using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetStudios
|
/// Class GetStudios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Studios", "GET")]
|
[Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
|
||||||
[Api(Description = "Gets all studios from a given item, folder, or the entire library")]
|
|
||||||
public class GetStudios : GetItemsByName
|
public class GetStudios : GetItemsByName
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -24,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetStudio
|
/// Class GetStudio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Studios/{Name}", "GET")]
|
[Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
|
||||||
[Api(Description = "Gets a studio, by name")]
|
|
||||||
public class GetStudio : IReturn<BaseItemDto>
|
public class GetStudio : IReturn<BaseItemDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -705,7 +705,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
||||||
}
|
}
|
||||||
|
|
||||||
var session = GetSession();
|
var session = GetSession(_sessionManager);
|
||||||
|
|
||||||
var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
|
var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -719,15 +719,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionInfo GetSession()
|
|
||||||
{
|
|
||||||
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
|
|
||||||
|
|
||||||
return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
|
|
||||||
string.Equals(i.Client, auth.Client) &&
|
|
||||||
string.Equals(i.ApplicationVersion, auth.Version));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Posts the specified request.
|
/// Posts the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -744,7 +735,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
CanSeek = request.CanSeek,
|
CanSeek = request.CanSeek,
|
||||||
Item = item,
|
Item = item,
|
||||||
SessionId = GetSession().Id,
|
SessionId = GetSession(_sessionManager).Id,
|
||||||
QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
|
QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
|
||||||
MediaSourceId = request.MediaSourceId
|
MediaSourceId = request.MediaSourceId
|
||||||
};
|
};
|
||||||
|
@ -768,7 +759,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
PositionTicks = request.PositionTicks,
|
PositionTicks = request.PositionTicks,
|
||||||
IsMuted = request.IsMuted,
|
IsMuted = request.IsMuted,
|
||||||
IsPaused = request.IsPaused,
|
IsPaused = request.IsPaused,
|
||||||
SessionId = GetSession().Id,
|
SessionId = GetSession(_sessionManager).Id,
|
||||||
MediaSourceId = request.MediaSourceId
|
MediaSourceId = request.MediaSourceId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -787,7 +778,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
|
|
||||||
var item = _dtoService.GetItemByDtoId(request.Id, user.Id);
|
var item = _dtoService.GetItemByDtoId(request.Id, user.Id);
|
||||||
|
|
||||||
var session = GetSession();
|
var session = GetSession(_sessionManager);
|
||||||
|
|
||||||
var info = new PlaybackStopInfo
|
var info = new PlaybackStopInfo
|
||||||
{
|
{
|
||||||
|
@ -817,7 +808,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
var session = GetSession();
|
var session = GetSession(_sessionManager);
|
||||||
|
|
||||||
var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
|
var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace MediaBrowser.Api.WebSocket
|
||||||
/// <returns>Task{SystemInfo}.</returns>
|
/// <returns>Task{SystemInfo}.</returns>
|
||||||
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
|
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_sessionManager.Sessions.Select(_dtoService.GetSessionInfoDto));
|
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_dtoService.GetSessionInfoDto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,6 @@
|
||||||
<Compile Include="Security\PluginSecurityManager.cs" />
|
<Compile Include="Security\PluginSecurityManager.cs" />
|
||||||
<Compile Include="Serialization\JsonSerializer.cs" />
|
<Compile Include="Serialization\JsonSerializer.cs" />
|
||||||
<Compile Include="Serialization\XmlSerializer.cs" />
|
<Compile Include="Serialization\XmlSerializer.cs" />
|
||||||
<Compile Include="Updates\ApplicationUpdater.cs" />
|
|
||||||
<Compile Include="Updates\InstallationManager.cs" />
|
<Compile Include="Updates\InstallationManager.cs" />
|
||||||
<Compile Include="Security\UsageReporter.cs" />
|
<Compile Include="Security\UsageReporter.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class CodecProfile
|
public class CodecProfile
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("type")]
|
||||||
public CodecType Type { get; set; }
|
public CodecType Type { get; set; }
|
||||||
|
|
||||||
public ProfileCondition[] Conditions { get; set; }
|
public ProfileCondition[] Conditions { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("codec")]
|
||||||
public string Codec { get; set; }
|
public string Codec { get; set; }
|
||||||
|
|
||||||
public CodecProfile()
|
public CodecProfile()
|
||||||
|
@ -30,16 +35,23 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
|
|
||||||
public enum CodecType
|
public enum CodecType
|
||||||
{
|
{
|
||||||
VideoCodec = 0,
|
Video = 0,
|
||||||
VideoAudioCodec = 1,
|
VideoAudio = 1,
|
||||||
AudioCodec = 2
|
Audio = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProfileCondition
|
public class ProfileCondition
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("condition")]
|
||||||
public ProfileConditionType Condition { get; set; }
|
public ProfileConditionType Condition { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("property")]
|
||||||
public ProfileConditionValue Property { get; set; }
|
public ProfileConditionValue Property { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("value")]
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("isRequired")]
|
||||||
public bool IsRequired { get; set; }
|
public bool IsRequired { get; set; }
|
||||||
|
|
||||||
public ProfileCondition()
|
public ProfileCondition()
|
||||||
|
@ -69,8 +81,6 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
VideoBitrate,
|
VideoBitrate,
|
||||||
VideoFramerate,
|
VideoFramerate,
|
||||||
VideoLevel,
|
VideoLevel,
|
||||||
VideoPacketLength,
|
VideoProfile
|
||||||
VideoProfile,
|
|
||||||
VideoTimestamp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class ContainerProfile
|
public class ContainerProfile
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
public ProfileCondition[] Conditions { get; set; }
|
public ProfileCondition[] Conditions { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
public ContainerProfile()
|
public ContainerProfile()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class DeviceIdentification
|
public class DeviceIdentification
|
||||||
|
@ -41,9 +43,7 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the manufacturer.
|
/// Gets or sets the manufacturer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>The manufacturer.</value>
|
||||||
/// The manufacturer.
|
|
||||||
/// </value>
|
|
||||||
public string Manufacturer { get; set; }
|
public string Manufacturer { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the manufacturer URL.
|
/// Gets or sets the manufacturer URL.
|
||||||
|
@ -64,8 +64,13 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
|
|
||||||
public class HttpHeaderInfo
|
public class HttpHeaderInfo
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("value")]
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("match")]
|
||||||
public HeaderMatchType Match { get; set; }
|
public HeaderMatchType Match { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class DeviceProfile
|
public class DeviceProfile
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -9,25 +16,11 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
[XmlIgnore]
|
||||||
/// Gets or sets the type of the client.
|
public string Id { get; set; }
|
||||||
/// </summary>
|
|
||||||
/// <value>The type of the client.</value>
|
|
||||||
public string ClientType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
[XmlIgnore]
|
||||||
/// Gets or sets the transcoding profiles.
|
public DeviceProfileType ProfileType { get; set; }
|
||||||
/// </summary>
|
|
||||||
/// <value>The transcoding profiles.</value>
|
|
||||||
public TranscodingProfile[] TranscodingProfiles { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the direct play profiles.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The direct play profiles.</value>
|
|
||||||
public DirectPlayProfile[] DirectPlayProfiles { get; set; }
|
|
||||||
|
|
||||||
public ContainerProfile[] ContainerProfiles { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the identification.
|
/// Gets or sets the identification.
|
||||||
|
@ -43,7 +36,9 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
public string ModelNumber { get; set; }
|
public string ModelNumber { get; set; }
|
||||||
public string ModelUrl { get; set; }
|
public string ModelUrl { get; set; }
|
||||||
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
||||||
public bool SupportsAlbumArtInDidl { get; set; }
|
public bool EnableAlbumArtInDidl { get; set; }
|
||||||
|
|
||||||
|
public string SupportedMediaTypes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
|
/// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
|
||||||
|
@ -60,14 +55,27 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
|
|
||||||
public string ProtocolInfo { get; set; }
|
public string ProtocolInfo { get; set; }
|
||||||
|
|
||||||
public MediaProfile[] MediaProfiles { get; set; }
|
|
||||||
public CodecProfile[] CodecProfiles { get; set; }
|
|
||||||
|
|
||||||
public int TimelineOffsetSeconds { get; set; }
|
public int TimelineOffsetSeconds { get; set; }
|
||||||
|
|
||||||
public bool RequiresPlainVideoItems { get; set; }
|
public bool RequiresPlainVideoItems { get; set; }
|
||||||
public bool RequiresPlainFolders { get; set; }
|
public bool RequiresPlainFolders { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the direct play profiles.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The direct play profiles.</value>
|
||||||
|
public DirectPlayProfile[] DirectPlayProfiles { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the transcoding profiles.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The transcoding profiles.</value>
|
||||||
|
public TranscodingProfile[] TranscodingProfiles { get; set; }
|
||||||
|
|
||||||
|
public ContainerProfile[] ContainerProfiles { get; set; }
|
||||||
|
|
||||||
|
public CodecProfile[] CodecProfiles { get; set; }
|
||||||
|
public MediaProfile[] MediaProfiles { get; set; }
|
||||||
|
|
||||||
public DeviceProfile()
|
public DeviceProfile()
|
||||||
{
|
{
|
||||||
DirectPlayProfiles = new DirectPlayProfile[] { };
|
DirectPlayProfiles = new DirectPlayProfile[] { };
|
||||||
|
@ -75,6 +83,149 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
MediaProfiles = new MediaProfile[] { };
|
MediaProfiles = new MediaProfile[] { };
|
||||||
CodecProfiles = new CodecProfile[] { };
|
CodecProfiles = new CodecProfile[] { };
|
||||||
ContainerProfiles = new ContainerProfile[] { };
|
ContainerProfiles = new ContainerProfile[] { };
|
||||||
|
|
||||||
|
SupportedMediaTypes = "Audio,Photo,Video";
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GetSupportedMediaTypes()
|
||||||
|
{
|
||||||
|
return (SupportedMediaTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
|
||||||
|
{
|
||||||
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
|
return TranscodingProfiles.FirstOrDefault(i =>
|
||||||
|
{
|
||||||
|
if (i.Type != DlnaProfileType.Audio)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
|
||||||
|
{
|
||||||
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
|
return TranscodingProfiles.FirstOrDefault(i =>
|
||||||
|
{
|
||||||
|
if (i.Type != DlnaProfileType.Video)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(videoCodec, i.VideoCodec, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaProfile GetAudioMediaProfile(string container, string audioCodec, MediaStream audioStream)
|
||||||
|
{
|
||||||
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
|
return MediaProfiles.FirstOrDefault(i =>
|
||||||
|
{
|
||||||
|
if (i.Type != DlnaProfileType.Audio)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var containers = i.GetContainers().ToList();
|
||||||
|
if (containers.Count > 0 && !containers.Contains(container))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var audioCodecs = i.GetAudioCodecs().ToList();
|
||||||
|
if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, MediaStream audioStream, MediaStream videoStream)
|
||||||
|
{
|
||||||
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
|
return MediaProfiles.FirstOrDefault(i =>
|
||||||
|
{
|
||||||
|
if (i.Type != DlnaProfileType.Video)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var containers = i.GetContainers().ToList();
|
||||||
|
if (containers.Count > 0 && !containers.Contains(container))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var audioCodecs = i.GetAudioCodecs().ToList();
|
||||||
|
if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoCodecs = i.GetVideoCodecs().ToList();
|
||||||
|
if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaProfile GetPhotoMediaProfile(string container)
|
||||||
|
{
|
||||||
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
|
return MediaProfiles.FirstOrDefault(i =>
|
||||||
|
{
|
||||||
|
if (i.Type != DlnaProfileType.Photo)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var containers = i.GetContainers().ToList();
|
||||||
|
if (containers.Count > 0 && !containers.Contains(container))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class DirectPlayProfile
|
public class DirectPlayProfile
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("audioCodec")]
|
||||||
public string AudioCodec { get; set; }
|
public string AudioCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("videoCodec")]
|
||||||
public string VideoCodec { get; set; }
|
public string VideoCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
public List<string> GetContainers()
|
public List<string> GetContainers()
|
||||||
|
|
|
@ -1,21 +1,54 @@
|
||||||
using System.Collections.Generic;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public interface IDlnaManager
|
public interface IDlnaManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the dlna profiles.
|
/// Gets the profile infos.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{DlnaProfile}.</returns>
|
/// <returns>IEnumerable{DeviceProfileInfo}.</returns>
|
||||||
IEnumerable<DeviceProfile> GetProfiles();
|
IEnumerable<DeviceProfileInfo> GetProfileInfos();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the profile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="headers">The headers.</param>
|
||||||
|
/// <returns>DeviceProfile.</returns>
|
||||||
|
DeviceProfile GetProfile(IDictionary<string,string> headers);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default profile.
|
/// Gets the default profile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>DlnaProfile.</returns>
|
/// <returns>DeviceProfile.</returns>
|
||||||
DeviceProfile GetDefaultProfile();
|
DeviceProfile GetDefaultProfile();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the profile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile.</param>
|
||||||
|
void CreateProfile(DeviceProfile profile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the profile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile.</param>
|
||||||
|
void UpdateProfile(DeviceProfile profile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the profile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
void DeleteProfile(string id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the profile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <returns>DeviceProfile.</returns>
|
||||||
|
DeviceProfile GetProfile(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the profile.
|
/// Gets the profile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class MediaProfile
|
public class MediaProfile
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("audioCodec")]
|
||||||
public string AudioCodec { get; set; }
|
public string AudioCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("videoCodec")]
|
||||||
public string VideoCodec { get; set; }
|
public string VideoCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("orgPn")]
|
||||||
public string OrgPn { get; set; }
|
public string OrgPn { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("mimeType")]
|
||||||
public string MimeType { get; set; }
|
public string MimeType { get; set; }
|
||||||
|
|
||||||
public ProfileCondition[] Conditions { get; set; }
|
public ProfileCondition[] Conditions { get; set; }
|
||||||
|
@ -19,6 +30,11 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
Conditions = new ProfileCondition[] {};
|
Conditions = new ProfileCondition[] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<string> GetContainers()
|
||||||
|
{
|
||||||
|
return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public List<string> GetAudioCodecs()
|
public List<string> GetAudioCodecs()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,17 +1,33 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public class TranscodingProfile
|
public class TranscodingProfile
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("videoCodec")]
|
||||||
public string VideoCodec { get; set; }
|
public string VideoCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("audioCodec")]
|
||||||
public string AudioCodec { get; set; }
|
public string AudioCodec { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("protocol")]
|
||||||
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("estimateContentLength")]
|
||||||
public bool EstimateContentLength { get; set; }
|
public bool EstimateContentLength { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("enableMpegtsM2TsMode")]
|
||||||
|
public bool EnableMpegtsM2TsMode { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("transcodeSeekInfo")]
|
||||||
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
||||||
|
|
||||||
public TranscodingSetting[] Settings { get; set; }
|
public TranscodingSetting[] Settings { get; set; }
|
||||||
|
@ -21,12 +37,19 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
Settings = new TranscodingSetting[] { };
|
Settings = new TranscodingSetting[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool EnableMpegtsM2TsMode { get; set; }
|
|
||||||
|
public List<string> GetAudioCodecs()
|
||||||
|
{
|
||||||
|
return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TranscodingSetting
|
public class TranscodingSetting
|
||||||
{
|
{
|
||||||
|
[XmlAttribute("name")]
|
||||||
public TranscodingSettingType Name { get; set; }
|
public TranscodingSettingType Name { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute("value")]
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The preferred metadata country code.</value>
|
/// <value>The preferred metadata country code.</value>
|
||||||
public string PreferredMetadataCountryCode { get; set; }
|
public string PreferredMetadataCountryCode { get; set; }
|
||||||
|
|
||||||
public Trailer()
|
public Trailer()
|
||||||
{
|
{
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
|
@ -33,19 +34,19 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
public float? Metascore { get; set; }
|
public float? Metascore { get; set; }
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
public List<string> Keywords { get; set; }
|
public List<string> Keywords { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the taglines.
|
/// Gets or sets the taglines.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The taglines.</value>
|
/// <value>The taglines.</value>
|
||||||
public List<string> Taglines { get; set; }
|
public List<string> Taglines { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the budget.
|
/// Gets or sets the budget.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -92,6 +93,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
key = key + "-trailer";
|
key = key + "-trailer";
|
||||||
|
|
||||||
|
// Make sure different trailers have their own data.
|
||||||
|
if (RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,10 +121,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
_configuration = value;
|
_configuration = value;
|
||||||
|
|
||||||
if (value == null)
|
_configurationInitialized = value != null;
|
||||||
{
|
|
||||||
_configurationInitialized = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,7 @@
|
||||||
<Compile Include="Localization\ILocalizationManager.cs" />
|
<Compile Include="Localization\ILocalizationManager.cs" />
|
||||||
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
||||||
<Compile Include="MediaEncoding\IEncodingManager.cs" />
|
<Compile Include="MediaEncoding\IEncodingManager.cs" />
|
||||||
|
<Compile Include="MediaEncoding\ImageEncodingOptions.cs" />
|
||||||
<Compile Include="MediaEncoding\IMediaEncoder.cs" />
|
<Compile Include="MediaEncoding\IMediaEncoder.cs" />
|
||||||
<Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
|
<Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
|
||||||
<Compile Include="Net\IHasResultFactory.cs" />
|
<Compile Include="Net\IHasResultFactory.cs" />
|
||||||
|
@ -187,6 +188,7 @@
|
||||||
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
||||||
<Compile Include="Providers\NameParser.cs" />
|
<Compile Include="Providers\NameParser.cs" />
|
||||||
<Compile Include="Providers\MetadataStatus.cs" />
|
<Compile Include="Providers\MetadataStatus.cs" />
|
||||||
|
<Compile Include="Providers\ISeriesOrderManager.cs" />
|
||||||
<Compile Include="Session\ISessionManager.cs" />
|
<Compile Include="Session\ISessionManager.cs" />
|
||||||
<Compile Include="Drawing\ImageExtensions.cs" />
|
<Compile Include="Drawing\ImageExtensions.cs" />
|
||||||
<Compile Include="Entities\AggregateFolder.cs" />
|
<Compile Include="Entities\AggregateFolder.cs" />
|
||||||
|
|
|
@ -24,16 +24,23 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
string Version { get; }
|
string Version { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the image.
|
/// Extracts the audio image.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{Stream}.</returns>
|
||||||
|
Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extracts the video image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inputFiles">The input files.</param>
|
/// <param name="inputFiles">The input files.</param>
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <param name="isAudio">if set to <c>true</c> [is audio].</param>
|
|
||||||
/// <param name="threedFormat">The threed format.</param>
|
/// <param name="threedFormat">The threed format.</param>
|
||||||
/// <param name="offset">The offset.</param>
|
/// <param name="offset">The offset.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the text subtitle.
|
/// Extracts the text subtitle.
|
||||||
|
@ -81,6 +88,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetInputArgument(string[] inputFiles, InputType type);
|
string GetInputArgument(string[] inputFiles, InputType type);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the image.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{Stream}.</returns>
|
||||||
|
Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using MediaBrowser.Model.Entities;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.MediaEncoding
|
namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
|
@ -24,7 +23,18 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// Gets or sets the chapters.
|
/// Gets or sets the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The chapters.</value>
|
/// <value>The chapters.</value>
|
||||||
public List<ChapterInfo> Chapters { get; set; }
|
public MediaChapter[] Chapters { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MediaChapter
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string time_base { get; set; }
|
||||||
|
public long start { get; set; }
|
||||||
|
public string start_time { get; set; }
|
||||||
|
public long end { get; set; }
|
||||||
|
public string end_time { get; set; }
|
||||||
|
public Dictionary<string, string> tags { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -154,7 +154,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
Codec = streamInfo.codec_name,
|
Codec = streamInfo.codec_name,
|
||||||
Profile = streamInfo.profile,
|
Profile = streamInfo.profile,
|
||||||
Level = streamInfo.level,
|
Level = streamInfo.level,
|
||||||
Index = streamInfo.index
|
Index = streamInfo.index,
|
||||||
|
PixelFormat = streamInfo.pix_fmt
|
||||||
};
|
};
|
||||||
|
|
||||||
if (streamInfo.tags != null)
|
if (streamInfo.tags != null)
|
||||||
|
@ -196,24 +197,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get stream bitrate
|
// Get stream bitrate
|
||||||
if (stream.Type != MediaStreamType.Subtitle)
|
var bitrate = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(streamInfo.bit_rate))
|
||||||
{
|
{
|
||||||
var bitrate = 0;
|
bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
|
||||||
|
}
|
||||||
|
else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video)
|
||||||
|
{
|
||||||
|
// If the stream info doesn't have a bitrate get the value from the media format info
|
||||||
|
bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(streamInfo.bit_rate))
|
if (bitrate > 0)
|
||||||
{
|
{
|
||||||
bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
|
stream.BitRate = bitrate;
|
||||||
}
|
|
||||||
else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate))
|
|
||||||
{
|
|
||||||
// If the stream info doesn't have a bitrate get the value from the media format info
|
|
||||||
bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitrate > 0)
|
|
||||||
{
|
|
||||||
stream.BitRate = bitrate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streamInfo.disposition != null)
|
if (streamInfo.disposition != null)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
@ -284,22 +283,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "TagLine":
|
|
||||||
{
|
|
||||||
var tagline = reader.ReadElementContentAsString();
|
|
||||||
|
|
||||||
var hasTaglines = item as IHasTaglines;
|
|
||||||
if (hasTaglines != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(tagline))
|
|
||||||
{
|
|
||||||
hasTaglines.AddTagline(tagline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "Language":
|
case "Language":
|
||||||
{
|
{
|
||||||
var val = reader.ReadElementContentAsString();
|
var val = reader.ReadElementContentAsString();
|
||||||
|
@ -380,9 +363,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
|
|
||||||
case "ContentRating":
|
case "ContentRating":
|
||||||
case "certification":
|
|
||||||
case "MPAARating":
|
case "MPAARating":
|
||||||
case "ESRBRating":
|
|
||||||
{
|
{
|
||||||
var rating = reader.ReadElementContentAsString();
|
var rating = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
|
@ -415,7 +396,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "Runtime":
|
|
||||||
case "RunningTime":
|
case "RunningTime":
|
||||||
{
|
{
|
||||||
var text = reader.ReadElementContentAsString();
|
var text = reader.ReadElementContentAsString();
|
||||||
|
@ -431,19 +411,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "Genre":
|
|
||||||
{
|
|
||||||
foreach (var name in SplitNames(reader.ReadElementContentAsString()))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
item.AddGenre(name);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "AspectRatio":
|
case "AspectRatio":
|
||||||
{
|
{
|
||||||
var val = reader.ReadElementContentAsString();
|
var val = reader.ReadElementContentAsString();
|
||||||
|
@ -587,7 +554,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "ReleaseYear":
|
|
||||||
case "ProductionYear":
|
case "ProductionYear":
|
||||||
{
|
{
|
||||||
var val = reader.ReadElementContentAsString();
|
var val = reader.ReadElementContentAsString();
|
||||||
|
@ -606,7 +572,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
|
|
||||||
case "Rating":
|
case "Rating":
|
||||||
case "IMDBrating":
|
case "IMDBrating":
|
||||||
case "TGDBRating":
|
|
||||||
{
|
{
|
||||||
|
|
||||||
var rating = reader.ReadElementContentAsString();
|
var rating = reader.ReadElementContentAsString();
|
||||||
|
@ -683,22 +648,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "MusicbrainzId":
|
|
||||||
{
|
|
||||||
var mbz = reader.ReadElementContentAsString();
|
|
||||||
if (!string.IsNullOrWhiteSpace(mbz))
|
|
||||||
{
|
|
||||||
if (item is MusicAlbum)
|
|
||||||
{
|
|
||||||
item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz);
|
|
||||||
}
|
|
||||||
else if (item is MusicArtist)
|
|
||||||
{
|
|
||||||
item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "MusicBrainzAlbumId":
|
case "MusicBrainzAlbumId":
|
||||||
{
|
{
|
||||||
var mbz = reader.ReadElementContentAsString();
|
var mbz = reader.ReadElementContentAsString();
|
||||||
|
@ -802,9 +751,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "IMDB_ID":
|
|
||||||
case "IMDB":
|
case "IMDB":
|
||||||
case "IMDbId":
|
|
||||||
var imDbId = reader.ReadElementContentAsString();
|
var imDbId = reader.ReadElementContentAsString();
|
||||||
if (!string.IsNullOrWhiteSpace(imDbId))
|
if (!string.IsNullOrWhiteSpace(imDbId))
|
||||||
{
|
{
|
||||||
|
@ -856,15 +803,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "ParentalRating":
|
|
||||||
{
|
|
||||||
using (var subtree = reader.ReadSubtree())
|
|
||||||
{
|
|
||||||
FetchFromParentalRatingNode(subtree, item);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "Studios":
|
case "Studios":
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
@ -1227,32 +1165,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetches from parental rating node.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reader">The reader.</param>
|
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
private void FetchFromParentalRatingNode(XmlReader reader, T item)
|
|
||||||
{
|
|
||||||
reader.MoveToContent();
|
|
||||||
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
|
||||||
{
|
|
||||||
switch (reader.Name)
|
|
||||||
{
|
|
||||||
// Removed support for "Value" tag as it conflicted with MPAA rating but leaving this function for possible
|
|
||||||
// future support of "Description" -ebr
|
|
||||||
|
|
||||||
default:
|
|
||||||
reader.Skip();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the persons from XML node.
|
/// Gets the persons from XML node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
26
MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
Normal file
26
MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,14 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
|
Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the generic command.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">The command.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends the library update info.
|
/// Sends the library update info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Dlna.Profiles;
|
using MediaBrowser.Dlna.Profiles;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
@ -11,21 +16,36 @@ namespace MediaBrowser.Dlna
|
||||||
{
|
{
|
||||||
public class DlnaManager : IDlnaManager
|
public class DlnaManager : IDlnaManager
|
||||||
{
|
{
|
||||||
private IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IXmlSerializer _xmlSerializer;
|
private readonly IXmlSerializer _xmlSerializer;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
|
public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IApplicationPaths appPaths, ILogger logger)
|
||||||
{
|
{
|
||||||
_xmlSerializer = xmlSerializer;
|
_xmlSerializer = xmlSerializer;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_jsonSerializer = jsonSerializer;
|
_appPaths = appPaths;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
GetProfiles();
|
//DumpProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<DeviceProfile> GetProfiles()
|
public IEnumerable<DeviceProfile> GetProfiles()
|
||||||
|
{
|
||||||
|
ExtractProfilesIfNeeded();
|
||||||
|
|
||||||
|
var list = GetProfiles(UserProfilesPath, DeviceProfileType.User)
|
||||||
|
.OrderBy(i => i.Name)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
list.AddRange(GetProfiles(SystemProfilesPath, DeviceProfileType.System)
|
||||||
|
.OrderBy(i => i.Name));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DumpProfiles()
|
||||||
{
|
{
|
||||||
var list = new List<DeviceProfile>
|
var list = new List<DeviceProfile>
|
||||||
{
|
{
|
||||||
|
@ -43,27 +63,72 @@ namespace MediaBrowser.Dlna
|
||||||
new WdtvLiveProfile(),
|
new WdtvLiveProfile(),
|
||||||
new DenonAvrProfile(),
|
new DenonAvrProfile(),
|
||||||
new LinksysDMA2100Profile(),
|
new LinksysDMA2100Profile(),
|
||||||
new LgTvProfile()
|
new LgTvProfile(),
|
||||||
|
new Foobar2000Profile(),
|
||||||
|
new DefaultProfile()
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
//_xmlSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".xml");
|
var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
|
||||||
//_jsonSerializer.SerializeToFile(item, "d:\\" + _fileSystem.GetValidFilename(item.Name) + ".json");
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
_xmlSerializer.SerializeToFile(item, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _extracted;
|
||||||
|
private readonly object _syncLock = new object();
|
||||||
|
private void ExtractProfilesIfNeeded()
|
||||||
|
{
|
||||||
|
if (!_extracted)
|
||||||
|
{
|
||||||
|
lock (_syncLock)
|
||||||
|
{
|
||||||
|
if (!_extracted)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ExtractSystemProfiles();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error extracting DLNA profiles.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
_extracted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceProfile GetDefaultProfile()
|
public DeviceProfile GetDefaultProfile()
|
||||||
{
|
{
|
||||||
|
ExtractProfilesIfNeeded();
|
||||||
|
|
||||||
return new DefaultProfile();
|
return new DefaultProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceProfile GetProfile(DeviceIdentification deviceInfo)
|
public DeviceProfile GetProfile(DeviceIdentification deviceInfo)
|
||||||
{
|
{
|
||||||
return GetProfiles().FirstOrDefault(i => IsMatch(deviceInfo, i.Identification)) ??
|
if (deviceInfo == null)
|
||||||
GetDefaultProfile();
|
{
|
||||||
|
throw new ArgumentNullException("deviceInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
var profile = GetProfiles()
|
||||||
|
.FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification));
|
||||||
|
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
_logger.Debug("Found matching device profile: {0}", profile.Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Debug("No matching device profile found. The default will need to be used.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMatch(DeviceIdentification deviceInfo, DeviceIdentification profileInfo)
|
private bool IsMatch(DeviceIdentification deviceInfo, DeviceIdentification profileInfo)
|
||||||
|
@ -124,5 +189,208 @@ namespace MediaBrowser.Dlna
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeviceProfile GetProfile(IDictionary<string, string> headers)
|
||||||
|
{
|
||||||
|
if (headers == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("headers");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)
|
||||||
|
{
|
||||||
|
return profileInfo.Headers.Any(i => IsMatch(headers, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsMatch(IDictionary<string, string> headers, HttpHeaderInfo header)
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
|
||||||
|
if (headers.TryGetValue(header.Name, out value))
|
||||||
|
{
|
||||||
|
switch (header.Match)
|
||||||
|
{
|
||||||
|
case HeaderMatchType.Equals:
|
||||||
|
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
|
||||||
|
case HeaderMatchType.Substring:
|
||||||
|
return value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
|
case HeaderMatchType.Regex:
|
||||||
|
return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase);
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unrecognized HeaderMatchType");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string UserProfilesPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SystemProfilesPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<DeviceProfile> GetProfiles(string path, DeviceProfileType type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new DirectoryInfo(path)
|
||||||
|
.EnumerateFiles("*", SearchOption.TopDirectoryOnly)
|
||||||
|
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(i => ParseProfileXmlFile(i.FullName, type))
|
||||||
|
.Where(i => i != null)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
return new List<DeviceProfile>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeviceProfile ParseProfileXmlFile(string path, DeviceProfileType type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var profile = (DeviceProfile)_xmlSerializer.DeserializeFromFile(typeof(DeviceProfile), path);
|
||||||
|
|
||||||
|
profile.Id = path.ToLower().GetMD5().ToString("N");
|
||||||
|
profile.ProfileType = type;
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error parsing profile xml: {0}", ex, path);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceProfile GetProfile(string id)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, id));
|
||||||
|
|
||||||
|
return ParseProfileXmlFile(info.Path, info.Info.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<InternalProfileInfo> GetProfileInfosInternal()
|
||||||
|
{
|
||||||
|
ExtractProfilesIfNeeded();
|
||||||
|
|
||||||
|
return GetProfileInfos(UserProfilesPath, DeviceProfileType.User)
|
||||||
|
.Concat(GetProfileInfos(SystemProfilesPath, DeviceProfileType.System))
|
||||||
|
.OrderBy(i => i.Info.Type == DeviceProfileType.User ? 0 : 1)
|
||||||
|
.ThenBy(i => i.Info.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DeviceProfileInfo> GetProfileInfos()
|
||||||
|
{
|
||||||
|
return GetProfileInfosInternal().Select(i => i.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<InternalProfileInfo> GetProfileInfos(string path, DeviceProfileType type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new DirectoryInfo(path)
|
||||||
|
.EnumerateFiles("*", SearchOption.TopDirectoryOnly)
|
||||||
|
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(i => new InternalProfileInfo
|
||||||
|
{
|
||||||
|
Path = i.FullName,
|
||||||
|
|
||||||
|
Info = new DeviceProfileInfo
|
||||||
|
{
|
||||||
|
Id = i.FullName.ToLower().GetMD5().ToString("N"),
|
||||||
|
Name = Path.GetFileNameWithoutExtension(i.FullName),
|
||||||
|
Type = type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
return new List<InternalProfileInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractSystemProfiles()
|
||||||
|
{
|
||||||
|
var assembly = GetType().Assembly;
|
||||||
|
var namespaceName = GetType().Namespace + ".Profiles.Xml.";
|
||||||
|
|
||||||
|
var systemProfilesPath = SystemProfilesPath;
|
||||||
|
|
||||||
|
foreach (var name in assembly.GetManifestResourceNames()
|
||||||
|
.Where(i => i.StartsWith(namespaceName))
|
||||||
|
.ToList())
|
||||||
|
{
|
||||||
|
var filename = Path.GetFileName(name).Substring(namespaceName.Length);
|
||||||
|
|
||||||
|
var path = Path.Combine(systemProfilesPath, filename);
|
||||||
|
|
||||||
|
using (var stream = assembly.GetManifestResourceStream(name))
|
||||||
|
{
|
||||||
|
var fileInfo = new FileInfo(path);
|
||||||
|
|
||||||
|
if (!fileInfo.Exists || fileInfo.Length != stream.Length)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(systemProfilesPath);
|
||||||
|
|
||||||
|
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||||
|
{
|
||||||
|
stream.CopyTo(fileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not necessary, but just to make it easy to find
|
||||||
|
Directory.CreateDirectory(UserProfilesPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteProfile(string id)
|
||||||
|
{
|
||||||
|
var info = GetProfileInfosInternal().First(i => string.Equals(id, i.Info.Id));
|
||||||
|
|
||||||
|
if (info.Info.Type == DeviceProfileType.System)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("System profiles cannot be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Delete(info.Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateProfile(DeviceProfile profile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProfile(DeviceProfile profile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalProfileInfo
|
||||||
|
{
|
||||||
|
internal DeviceProfileInfo Info { get; set; }
|
||||||
|
internal string Path { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -61,7 +61,6 @@
|
||||||
<Compile Include="PlayTo\DeviceService.cs" />
|
<Compile Include="PlayTo\DeviceService.cs" />
|
||||||
<Compile Include="PlayTo\DidlBuilder.cs" />
|
<Compile Include="PlayTo\DidlBuilder.cs" />
|
||||||
<Compile Include="PlayTo\DlnaController.cs" />
|
<Compile Include="PlayTo\DlnaController.cs" />
|
||||||
<Compile Include="PlayTo\DlnaControllerFactory.cs" />
|
|
||||||
<Compile Include="PlayTo\Extensions.cs" />
|
<Compile Include="PlayTo\Extensions.cs" />
|
||||||
<Compile Include="PlayTo\PlaylistItem.cs">
|
<Compile Include="PlayTo\PlaylistItem.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
@ -70,7 +69,8 @@
|
||||||
<Compile Include="PlayTo\PlayToManager.cs" />
|
<Compile Include="PlayTo\PlayToManager.cs" />
|
||||||
<Compile Include="PlayTo\PlayToServerEntryPoint.cs" />
|
<Compile Include="PlayTo\PlayToServerEntryPoint.cs" />
|
||||||
<Compile Include="PlayTo\ServiceAction.cs" />
|
<Compile Include="PlayTo\ServiceAction.cs" />
|
||||||
<Compile Include="PlayTo\SsdpHelper.cs" />
|
<Compile Include="Profiles\Foobar2000Profile.cs" />
|
||||||
|
<Compile Include="Ssdp\SsdpHelper.cs" />
|
||||||
<Compile Include="PlayTo\SsdpHttpClient.cs" />
|
<Compile Include="PlayTo\SsdpHttpClient.cs" />
|
||||||
<Compile Include="PlayTo\StateVariable.cs" />
|
<Compile Include="PlayTo\StateVariable.cs" />
|
||||||
<Compile Include="PlayTo\StreamHelper.cs" />
|
<Compile Include="PlayTo\StreamHelper.cs" />
|
||||||
|
@ -100,7 +100,6 @@
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Server\DlnaServerEntryPoint.cs" />
|
<Compile Include="Server\DlnaServerEntryPoint.cs" />
|
||||||
<Compile Include="Server\Headers.cs" />
|
<Compile Include="Server\Headers.cs" />
|
||||||
<Compile Include="Server\RawHeaders.cs" />
|
|
||||||
<Compile Include="Server\SsdpHandler.cs" />
|
<Compile Include="Server\SsdpHandler.cs" />
|
||||||
<Compile Include="Server\UpnpDevice.cs" />
|
<Compile Include="Server\UpnpDevice.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -118,7 +117,27 @@
|
||||||
<Name>MediaBrowser.Model</Name>
|
<Name>MediaBrowser.Model</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Denon AVR.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\foobar2000.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\LG Smart TV.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Linksys DMA2100.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Panasonic Viera.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Samsung Smart TV.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player 2013.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Blu-ray Player.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282010%29.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282011%29.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282012%29.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282013%29.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 3.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\WDTV Live.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Xbox 360.xml" />
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Default.xml" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|
|
@ -4,18 +4,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
public class CurrentIdEventArgs : EventArgs
|
public class CurrentIdEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
public CurrentIdEventArgs(string id)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(id) || id == "0")
|
|
||||||
{
|
|
||||||
Id = Guid.Empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Id = new Guid(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
if (_currentId == value)
|
if (_currentId == value)
|
||||||
return;
|
return;
|
||||||
_currentId = value;
|
_currentId = value;
|
||||||
|
|
||||||
NotifyCurrentIdChanged(value);
|
NotifyCurrentIdChanged(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +251,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
StopTimer();
|
StopTimer();
|
||||||
|
|
||||||
await SetStop().ConfigureAwait(false);
|
await SetStop().ConfigureAwait(false);
|
||||||
CurrentId = "0";
|
CurrentId = null;
|
||||||
|
|
||||||
var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
|
var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
|
@ -514,7 +515,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(track))
|
if (String.IsNullOrEmpty(track))
|
||||||
{
|
{
|
||||||
CurrentId = "0";
|
CurrentId = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +608,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
url = "/" + url;
|
url = "/" + url;
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
||||||
var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url));
|
var document = await httpClient.GetDataAsync(Properties.BaseUrl + url);
|
||||||
|
|
||||||
AvCommands = TransportCommands.Create(document);
|
AvCommands = TransportCommands.Create(document);
|
||||||
}
|
}
|
||||||
|
@ -625,12 +626,12 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
url = "/" + url;
|
url = "/" + url;
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
||||||
var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url));
|
var document = await httpClient.GetDataAsync(Properties.BaseUrl + url);
|
||||||
|
|
||||||
RendererCommands = TransportCommands.Create(document);
|
RendererCommands = TransportCommands.Create(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal TransportCommands AvCommands
|
private TransportCommands AvCommands
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
@ -646,7 +647,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
|
var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
|
||||||
|
|
||||||
var document = await ssdpHttpClient.GetDataAsync(url).ConfigureAwait(false);
|
var document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false);
|
||||||
|
|
||||||
var deviceProperties = new DeviceInfo();
|
var deviceProperties = new DeviceInfo();
|
||||||
|
|
||||||
|
@ -681,10 +682,18 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
var presentationUrl = document.Descendants(uPnpNamespaces.ud.GetName("presentationURL")).FirstOrDefault();
|
var presentationUrl = document.Descendants(uPnpNamespaces.ud.GetName("presentationURL")).FirstOrDefault();
|
||||||
if (presentationUrl != null)
|
if (presentationUrl != null)
|
||||||
deviceProperties.PresentationUrl = presentationUrl.Value;
|
deviceProperties.PresentationUrl = presentationUrl.Value;
|
||||||
|
|
||||||
var modelUrl = document.Descendants(uPnpNamespaces.ud.GetName("modelURL")).FirstOrDefault();
|
var modelUrl = document.Descendants(uPnpNamespaces.ud.GetName("modelURL")).FirstOrDefault();
|
||||||
if (modelUrl != null)
|
if (modelUrl != null)
|
||||||
deviceProperties.ModelUrl = modelUrl.Value;
|
deviceProperties.ModelUrl = modelUrl.Value;
|
||||||
|
|
||||||
|
var serialNumber = document.Descendants(uPnpNamespaces.ud.GetName("serialNumber")).FirstOrDefault();
|
||||||
|
if (serialNumber != null)
|
||||||
|
deviceProperties.SerialNumber = serialNumber.Value;
|
||||||
|
|
||||||
|
var modelDescription = document.Descendants(uPnpNamespaces.ud.GetName("modelDescription")).FirstOrDefault();
|
||||||
|
if (modelDescription != null)
|
||||||
|
deviceProperties.ModelDescription = modelDescription.Value;
|
||||||
|
|
||||||
deviceProperties.BaseUrl = String.Format("http://{0}:{1}", url.Host, url.Port);
|
deviceProperties.BaseUrl = String.Format("http://{0}:{1}", url.Host, url.Port);
|
||||||
|
|
||||||
|
@ -724,7 +733,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
if (isRenderer)
|
if (isRenderer)
|
||||||
{
|
{
|
||||||
|
|
||||||
var device = new Device(deviceProperties, httpClient, logger, config);
|
var device = new Device(deviceProperties, httpClient, logger, config);
|
||||||
|
|
||||||
await device.GetRenderingProtocolAsync().ConfigureAwait(false);
|
await device.GetRenderingProtocolAsync().ConfigureAwait(false);
|
||||||
|
@ -768,7 +776,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
private void NotifyCurrentIdChanged(string value)
|
private void NotifyCurrentIdChanged(string value)
|
||||||
{
|
{
|
||||||
if (CurrentIdChanged != null)
|
if (CurrentIdChanged != null)
|
||||||
CurrentIdChanged.Invoke(this, new CurrentIdEventArgs(value));
|
CurrentIdChanged.Invoke(this, new CurrentIdEventArgs { Id = value });
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.PlayTo
|
namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
@ -17,27 +17,18 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
public string ClientType { get; set; }
|
public string ClientType { get; set; }
|
||||||
|
|
||||||
private string _displayName = string.Empty;
|
|
||||||
public string DisplayName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return string.IsNullOrEmpty(_displayName) ? Name : _displayName;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_displayName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ModelName { get; set; }
|
public string ModelName { get; set; }
|
||||||
|
|
||||||
public string ModelNumber { get; set; }
|
public string ModelNumber { get; set; }
|
||||||
|
|
||||||
|
public string ModelDescription { get; set; }
|
||||||
|
|
||||||
public string ModelUrl { get; set; }
|
public string ModelUrl { get; set; }
|
||||||
|
|
||||||
public string Manufacturer { get; set; }
|
public string Manufacturer { get; set; }
|
||||||
|
|
||||||
|
public string SerialNumber { get; set; }
|
||||||
|
|
||||||
public string ManufacturerUrl { get; set; }
|
public string ManufacturerUrl { get; set; }
|
||||||
|
|
||||||
public string PresentationUrl { get; set; }
|
public string PresentationUrl { get; set; }
|
||||||
|
@ -75,7 +66,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
ModelNumber = ModelNumber,
|
ModelNumber = ModelNumber,
|
||||||
FriendlyName = Name,
|
FriendlyName = Name,
|
||||||
ManufacturerUrl = ManufacturerUrl,
|
ManufacturerUrl = ManufacturerUrl,
|
||||||
ModelUrl = ModelUrl
|
ModelUrl = ModelUrl,
|
||||||
|
ModelDescription = ModelDescription,
|
||||||
|
SerialNumber = SerialNumber
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,31 +9,27 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
internal class DidlBuilder
|
internal class DidlBuilder
|
||||||
{
|
{
|
||||||
#region Constants
|
const string CRLF = "\r\n";
|
||||||
|
const string UNKNOWN = "Unknown";
|
||||||
|
|
||||||
internal const string CRLF = "\r\n";
|
const string DIDL_START = @"<item id=""{0}"" parentID=""{1}"" restricted=""1"" xmlns=""urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"">" + CRLF;
|
||||||
internal const string UNKNOWN = "Unknown";
|
const string DIDL_TITLE = @" <dc:title xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:title>" + CRLF;
|
||||||
|
const string DIDL_ARTIST = @"<upnp:artist xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:artist>" + CRLF;
|
||||||
internal const string DIDL_START = @"<item id=""{0}"" parentID=""{1}"" restricted=""1"" xmlns=""urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"">" + CRLF;
|
const string DIDL_ALBUM = @"<upnp:album xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:album>" + CRLF;
|
||||||
internal const string DIDL_TITLE = @" <dc:title xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:title>" + CRLF;
|
const string DIDL_TRACKNUM = @"<upnp:originalTrackNumber xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:originalTrackNumber>" + CRLF;
|
||||||
internal const string DIDL_ARTIST = @"<upnp:artist xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:artist>" + CRLF;
|
const string DIDL_VIDEOCLASS = @" <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.videoItem</upnp:class>" + CRLF;
|
||||||
internal const string DIDL_ALBUM = @"<upnp:album xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:album>" + CRLF;
|
const string DIDL_AUDIOCLASS = @" <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.audioItem.musicTrack</upnp:class>" + CRLF;
|
||||||
internal const string DIDL_TRACKNUM = @"<upnp:originalTrackNumber xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">0</upnp:originalTrackNumber>" + CRLF;
|
const string DIDL_IMAGE = @" <upnp:albumArtURI dlna:profileID=""JPEG_TN"" xmlns:dlna=""urn:schemas-dlna-org:metadata-1-0/"" xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:albumArtURI>" + CRLF +
|
||||||
internal const string DIDL_VIDEOCLASS = @" <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.videoItem</upnp:class>" + CRLF;
|
@" <upnp:icon xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:icon>" + CRLF;
|
||||||
internal const string DIDL_AUDIOCLASS = @" <upnp:class xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">object.item.audioItem.musicTrack</upnp:class>" + CRLF;
|
const string DIDL_RELEASEDATE = @" <dc:date xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:date>" + CRLF;
|
||||||
internal const string DIDL_IMAGE = @" <upnp:albumArtURI dlna:profileID=""JPEG_TN"" xmlns:dlna=""urn:schemas-dlna-org:metadata-1-0/"" xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:albumArtURI>" + CRLF +
|
const string DIDL_GENRE = @" <upnp:genre xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:genre>" + CRLF;
|
||||||
@" <upnp:icon xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:icon>" + CRLF;
|
const string DESCRIPTION = @" <dc:description xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:description>" + CRLF;
|
||||||
internal const string DIDL_RELEASEDATE = @" <dc:date xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:date>" + CRLF;
|
const string DIDL_VIDEO_RES = @" <res bitrate=""{0}"" duration=""{1}"" protocolInfo=""http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" resolution=""{2}x{3}"" size=""0"">{4}</res>" + CRLF;
|
||||||
internal const string DIDL_GENRE = @" <upnp:genre xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:genre>" + CRLF;
|
const string DIDL_AUDIO_RES = @" <res bitrate=""{0}"" duration=""{1}"" nrAudioChannels=""2"" protocolInfo=""http-get:*:audio/mp3:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" sampleFrequency=""{2}"" size=""0"">{3}</res>" + CRLF;
|
||||||
internal const string DESCRIPTION = @" <dc:description xmlns:dc=""http://purl.org/dc/elements/1.1/"">{0}</dc:description>" + CRLF;
|
const string DIDL_IMAGE_RES = @" <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""212x320"">{0}</res>" + CRLF;
|
||||||
internal const string DIDL_VIDEO_RES = @" <res bitrate=""{0}"" duration=""{1}"" protocolInfo=""http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" resolution=""{2}x{3}"" size=""0"">{4}</res>" + CRLF;
|
const string DIDL_ALBUMIMAGE_RES = @" <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""320x320"">{0}</res>" + CRLF;
|
||||||
internal const string DIDL_AUDIO_RES = @" <res bitrate=""{0}"" duration=""{1}"" nrAudioChannels=""2"" protocolInfo=""http-get:*:audio/mp3:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"" sampleFrequency=""{2}"" size=""0"">{3}</res>" + CRLF;
|
const string DIDL_RATING = @" <upnp:rating xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:rating>" + CRLF;
|
||||||
internal const string DIDL_IMAGE_RES = @" <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""212x320"">{0}</res>" + CRLF;
|
const string DIDL_END = "</item>";
|
||||||
internal const string DIDL_ALBUMIMAGE_RES = @" <res protocolInfo=""http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00D00000000000000000000000000000"" resolution=""320x320"">{0}</res>" + CRLF;
|
|
||||||
internal const string DIDL_RATING = @" <upnp:rating xmlns:upnp=""urn:schemas-upnp-org:metadata-1-0/upnp/"">{0}</upnp:rating>" + CRLF;
|
|
||||||
internal const string DIDL_END = "</item>";
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Builds a Didl MetaData object for the specified dto.
|
/// Builds a Didl MetaData object for the specified dto.
|
||||||
|
@ -44,7 +40,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
/// <param name="streamUrl">The stream URL.</param>
|
/// <param name="streamUrl">The stream URL.</param>
|
||||||
/// <param name="streams">The streams.</param>
|
/// <param name="streams">The streams.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
internal static string Build(BaseItem dto, string userId, string serverAddress, string streamUrl, IEnumerable<MediaStream> streams)
|
public static string Build(BaseItem dto, string userId, string serverAddress, string streamUrl, IEnumerable<MediaStream> streams, bool includeImageRes)
|
||||||
{
|
{
|
||||||
string response = string.Format(DIDL_START, dto.Id, userId);
|
string response = string.Format(DIDL_START, dto.Id, userId);
|
||||||
response += string.Format(DIDL_TITLE, dto.Name.Replace("&", "and"));
|
response += string.Format(DIDL_TITLE, dto.Name.Replace("&", "and"));
|
||||||
|
@ -53,7 +49,12 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
else
|
else
|
||||||
response += DIDL_AUDIOCLASS;
|
response += DIDL_AUDIOCLASS;
|
||||||
|
|
||||||
response += string.Format(DIDL_IMAGE, GetImageUrl(dto, serverAddress));
|
var imageUrl = GetImageUrl(dto, serverAddress);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(imageUrl))
|
||||||
|
{
|
||||||
|
response += string.Format(DIDL_IMAGE, imageUrl);
|
||||||
|
}
|
||||||
response += string.Format(DIDL_RELEASEDATE, GetDateString(dto.PremiereDate));
|
response += string.Format(DIDL_RELEASEDATE, GetDateString(dto.PremiereDate));
|
||||||
|
|
||||||
//TODO Add genres to didl;
|
//TODO Add genres to didl;
|
||||||
|
@ -63,7 +64,11 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
response += string.Format(DESCRIPTION, UNKNOWN);
|
response += string.Format(DESCRIPTION, UNKNOWN);
|
||||||
response += GetVideoDIDL(dto, streamUrl, streams);
|
response += GetVideoDIDL(dto, streamUrl, streams);
|
||||||
response += string.Format(DIDL_IMAGE_RES, GetImageUrl(dto, serverAddress));
|
|
||||||
|
if (includeImageRes && !string.IsNullOrWhiteSpace(imageUrl))
|
||||||
|
{
|
||||||
|
response += string.Format(DIDL_IMAGE_RES, imageUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -74,25 +79,25 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
response += string.Format(DIDL_ARTIST, audio.Artists.FirstOrDefault() ?? UNKNOWN);
|
response += string.Format(DIDL_ARTIST, audio.Artists.FirstOrDefault() ?? UNKNOWN);
|
||||||
response += string.Format(DIDL_ALBUM, audio.Album);
|
response += string.Format(DIDL_ALBUM, audio.Album);
|
||||||
|
|
||||||
// TODO: Bad format string?
|
|
||||||
response += string.Format(DIDL_TRACKNUM, audio.IndexNumber ?? 0);
|
response += string.Format(DIDL_TRACKNUM, audio.IndexNumber ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
response += GetAudioDIDL(dto, streamUrl, streams);
|
response += GetAudioDIDL(dto, streamUrl, streams);
|
||||||
response += string.Format(DIDL_ALBUMIMAGE_RES, GetImageUrl(dto, serverAddress));
|
|
||||||
|
if (includeImageRes && !string.IsNullOrWhiteSpace(imageUrl))
|
||||||
|
{
|
||||||
|
response += string.Format(DIDL_ALBUMIMAGE_RES, imageUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response += DIDL_END;
|
response += DIDL_END;
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Private methods
|
|
||||||
|
|
||||||
private static string GetVideoDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
|
private static string GetVideoDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
|
||||||
{
|
{
|
||||||
var videostream = streams.Where(stream => stream.Type == Model.Entities.MediaStreamType.Video).OrderBy(s => s.IsDefault).FirstOrDefault();
|
var videostream = streams.Where(stream => stream.Type == MediaStreamType.Video).OrderBy(s => s.IsDefault ? 0 : 1).FirstOrDefault();
|
||||||
|
|
||||||
if (videostream == null)
|
if (videostream == null)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +110,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
private static string GetAudioDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
|
private static string GetAudioDIDL(BaseItem dto, string streamUrl, IEnumerable<MediaStream> streams)
|
||||||
{
|
{
|
||||||
var audiostream = streams.Where(stream => stream.Type == MediaStreamType.Audio).OrderBy(s => s.IsDefault).FirstOrDefault();
|
var audiostream = streams.Where(stream => stream.Type == MediaStreamType.Audio).OrderBy(s => s.IsDefault ? 0 : 1).FirstOrDefault();
|
||||||
|
|
||||||
if (audiostream == null)
|
if (audiostream == null)
|
||||||
{
|
{
|
||||||
|
@ -118,14 +123,14 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
private static string GetImageUrl(BaseItem dto, string serverAddress)
|
private static string GetImageUrl(BaseItem dto, string serverAddress)
|
||||||
{
|
{
|
||||||
var imageType = ImageType.Primary;
|
const ImageType imageType = ImageType.Primary;
|
||||||
|
|
||||||
if (!dto.HasImage(ImageType.Primary))
|
if (!dto.HasImage(imageType))
|
||||||
{
|
{
|
||||||
dto = dto.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
|
dto = dto.Parents.FirstOrDefault(i => i.HasImage(imageType));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format("{0}/Items/{1}/Images/{2}", serverAddress, dto.Id, imageType);
|
return dto == null ? null : string.Format("{0}/Items/{1}/Images/{2}", serverAddress, dto.Id, imageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDurationString(BaseItem dto)
|
private static string GetDurationString(BaseItem dto)
|
||||||
|
@ -148,7 +153,5 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
return string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
return string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
public class PlayToController : ISessionController, IDisposable
|
public class PlayToController : ISessionController, IDisposable
|
||||||
{
|
{
|
||||||
private Device _device;
|
private Device _device;
|
||||||
private BaseItem _currentItem = null;
|
private BaseItem _currentItem;
|
||||||
private readonly SessionInfo _session;
|
private readonly SessionInfo _session;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IItemRepository _itemRepository;
|
private readonly IItemRepository _itemRepository;
|
||||||
|
@ -30,7 +30,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
private readonly IDlnaManager _dlnaManager;
|
private readonly IDlnaManager _dlnaManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private bool _playbackStarted = false;
|
private bool _playbackStarted;
|
||||||
|
|
||||||
private const int UpdateTimerIntervalMs = 1000;
|
private const int UpdateTimerIntervalMs = 1000;
|
||||||
|
|
||||||
|
@ -103,22 +103,27 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
async void Device_CurrentIdChanged(object sender, CurrentIdEventArgs e)
|
async void Device_CurrentIdChanged(object sender, CurrentIdEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Id != Guid.Empty)
|
if (!string.IsNullOrWhiteSpace(e.Id))
|
||||||
{
|
{
|
||||||
if (_currentItem != null && _currentItem.Id == e.Id)
|
Guid guid;
|
||||||
|
|
||||||
|
if (Guid.TryParse(e.Id, out guid))
|
||||||
{
|
{
|
||||||
return;
|
if (_currentItem != null && _currentItem.Id == guid)
|
||||||
}
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var item = _libraryManager.GetItemById(e.Id);
|
var item = _libraryManager.GetItemById(guid);
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} - CurrentId {1}", _session.DeviceName, item.Id);
|
_logger.Debug("{0} - CurrentId {1}", _session.DeviceName, item.Id);
|
||||||
_currentItem = item;
|
_currentItem = item;
|
||||||
_playbackStarted = false;
|
_playbackStarted = false;
|
||||||
|
|
||||||
await ReportProgress().ConfigureAwait(false);
|
await ReportProgress().ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,8 +145,15 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
_updateTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
_updateTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||||
|
|
||||||
//Session is inactive, mark it for Disposal and don't start the elapsed timer.
|
try
|
||||||
await _sessionManager.ReportSessionEnded(_session.Id);
|
{
|
||||||
|
// Session is inactive, mark it for Disposal and don't start the elapsed timer.
|
||||||
|
await _sessionManager.ReportSessionEnded(_session.Id);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error in ReportSessionEnded", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +168,15 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
if (!_playbackStarted)
|
if (!_playbackStarted)
|
||||||
{
|
{
|
||||||
await _sessionManager.OnPlaybackStart(new PlaybackInfo { Item = _currentItem, SessionId = _session.Id, CanSeek = true, QueueableMediaTypes = new List<string> { "Audio", "Video" } }).ConfigureAwait(false);
|
await _sessionManager.OnPlaybackStart(new PlaybackInfo
|
||||||
|
{
|
||||||
|
Item = _currentItem,
|
||||||
|
SessionId = _session.Id,
|
||||||
|
CanSeek = true,
|
||||||
|
QueueableMediaTypes = new List<string> { _currentItem.MediaType }
|
||||||
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
_playbackStarted = true;
|
_playbackStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,11 +419,12 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
var deviceInfo = _device.Properties;
|
var deviceInfo = _device.Properties;
|
||||||
|
|
||||||
var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification());
|
var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ??
|
||||||
|
_dlnaManager.GetDefaultProfile();
|
||||||
|
|
||||||
var playlistItem = GetPlaylistItem(item, streams, profile);
|
var playlistItem = GetPlaylistItem(item, streams, profile);
|
||||||
playlistItem.StartPositionTicks = startPostionTicks;
|
playlistItem.StartPositionTicks = startPostionTicks;
|
||||||
playlistItem.DeviceProfileName = profile.Name;
|
playlistItem.DeviceProfileId = profile.Id;
|
||||||
|
|
||||||
if (playlistItem.MediaType == DlnaProfileType.Audio)
|
if (playlistItem.MediaType == DlnaProfileType.Audio)
|
||||||
{
|
{
|
||||||
|
@ -414,8 +435,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
playlistItem.StreamUrl = StreamHelper.GetVideoUrl(_device.Properties, playlistItem, streams, serverAddress);
|
playlistItem.StreamUrl = StreamHelper.GetVideoUrl(_device.Properties, playlistItem, streams, serverAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
var didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams);
|
playlistItem.Didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams, profile.EnableAlbumArtInDidl);
|
||||||
playlistItem.Didl = didl;
|
|
||||||
|
|
||||||
return playlistItem;
|
return playlistItem;
|
||||||
}
|
}
|
||||||
|
@ -599,5 +619,10 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
_logger.Log(LogSeverity.Debug, "Controller disposed");
|
_logger.Log(LogSeverity.Debug, "Controller disposed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,16 +5,17 @@ using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
|
using MediaBrowser.Dlna.Ssdp;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -126,10 +127,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
if (receivedBytes > 0)
|
if (receivedBytes > 0)
|
||||||
{
|
{
|
||||||
var rawData = Encoding.UTF8.GetString(receiveBuffer, 0, receivedBytes);
|
var headers = SsdpHelper.ParseSsdpResponse(receiveBuffer);
|
||||||
var uri = SsdpHelper.ParseSsdpResponse(rawData);
|
|
||||||
|
|
||||||
TryCreateController(uri);
|
TryCreateController(headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,13 +146,20 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}, _tokenSource.Token, TaskCreationOptions.LongRunning);
|
}, _tokenSource.Token, TaskCreationOptions.LongRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryCreateController(Uri uri)
|
private void TryCreateController(IDictionary<string,string> headers)
|
||||||
{
|
{
|
||||||
|
string location;
|
||||||
|
|
||||||
|
if (!headers.TryGetValue("Location", out location))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await CreateController(uri).ConfigureAwait(false);
|
await CreateController(new Uri(location)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
@ -221,46 +228,29 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive))
|
if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive))
|
||||||
{
|
{
|
||||||
GetProfileSettings(device.Properties);
|
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
|
||||||
|
|
||||||
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, device.Properties.Name, device.Properties.UUID, device.Properties.DisplayName, uri.OriginalString, null)
|
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
|
|
||||||
{
|
|
||||||
PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo },
|
|
||||||
SupportsFullscreenToggle = false
|
|
||||||
});
|
|
||||||
|
|
||||||
var controller = sessionInfo.SessionController as PlayToController;
|
var controller = sessionInfo.SessionController as PlayToController;
|
||||||
|
|
||||||
if (controller == null)
|
if (controller == null)
|
||||||
{
|
{
|
||||||
sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager, _dlnaManager, _userManager, _appHost);
|
sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager, _dlnaManager, _userManager, _appHost);
|
||||||
|
|
||||||
|
controller.Init(device);
|
||||||
|
|
||||||
|
var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
|
||||||
|
_dlnaManager.GetDefaultProfile();
|
||||||
|
|
||||||
|
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
|
||||||
|
{
|
||||||
|
PlayableMediaTypes = profile.GetSupportedMediaTypes().ToArray(),
|
||||||
|
|
||||||
|
SupportsFullscreenToggle = false
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.Init(device);
|
|
||||||
|
|
||||||
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the profile settings.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceProperties">The device properties.</param>
|
|
||||||
/// <returns>The TranscodeSettings for the device</returns>
|
|
||||||
private void GetProfileSettings(DeviceInfo deviceProperties)
|
|
||||||
{
|
|
||||||
var profile = _dlnaManager.GetProfile(deviceProperties.ToDeviceIdentification());
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(profile.Name))
|
|
||||||
{
|
|
||||||
deviceProperties.DisplayName = profile.Name;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrWhiteSpace(profile.ClientType))
|
|
||||||
{
|
|
||||||
deviceProperties.ClientType = profile.ClientType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
public int? SubtitleStreamIndex { get; set; }
|
public int? SubtitleStreamIndex { get; set; }
|
||||||
|
|
||||||
public string DeviceProfileName { get; set; }
|
|
||||||
|
|
||||||
public int? MaxAudioChannels { get; set; }
|
public int? MaxAudioChannels { get; set; }
|
||||||
|
|
||||||
public int? AudioBitrate { get; set; }
|
public int? AudioBitrate { get; set; }
|
||||||
|
@ -48,6 +46,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
public int? MaxFramerate { get; set; }
|
public int? MaxFramerate { get; set; }
|
||||||
|
|
||||||
|
public string DeviceProfileId { get; set; }
|
||||||
|
|
||||||
public PlaylistItem()
|
public PlaylistItem()
|
||||||
{
|
{
|
||||||
TranscodingSettings = new List<TranscodingSetting>();
|
TranscodingSettings = new List<TranscodingSetting>();
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
var audioCodec = audioStream == null ? null : audioStream.Codec;
|
var audioCodec = audioStream == null ? null : audioStream.Codec;
|
||||||
|
|
||||||
// Make sure audio codec profiles are satisfied
|
// Make sure audio codec profiles are satisfied
|
||||||
if (!string.IsNullOrEmpty(audioCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.AudioCodec && i.ContainsCodec(audioCodec))
|
if (!string.IsNullOrEmpty(audioCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
|
||||||
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, null, audioStream)))
|
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, null, audioStream)))
|
||||||
{
|
{
|
||||||
playlistItem.Transcode = false;
|
playlistItem.Transcode = false;
|
||||||
|
@ -53,7 +53,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
|
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
|
||||||
|
|
||||||
var audioTranscodingConditions = profile.CodecProfiles
|
var audioTranscodingConditions = profile.CodecProfiles
|
||||||
.Where(i => i.Type == CodecType.AudioCodec && i.ContainsCodec(transcodingProfile.AudioCodec))
|
.Where(i => i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
||||||
.Take(1)
|
.Take(1)
|
||||||
.SelectMany(i => i.Conditions);
|
.SelectMany(i => i.Conditions);
|
||||||
|
|
||||||
|
@ -114,13 +114,13 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
var videoCodec = videoStream == null ? null : videoStream.Codec;
|
var videoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
|
||||||
// Make sure video codec profiles are satisfied
|
// Make sure video codec profiles are satisfied
|
||||||
if (!string.IsNullOrEmpty(videoCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.VideoCodec && i.ContainsCodec(videoCodec))
|
if (!string.IsNullOrEmpty(videoCodec) && profile.CodecProfiles.Where(i => i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
|
||||||
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
|
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
|
||||||
{
|
{
|
||||||
var audioCodec = audioStream == null ? null : audioStream.Codec;
|
var audioCodec = audioStream == null ? null : audioStream.Codec;
|
||||||
|
|
||||||
// Make sure audio codec profiles are satisfied
|
// Make sure audio codec profiles are satisfied
|
||||||
if (string.IsNullOrEmpty(audioCodec) || profile.CodecProfiles.Where(i => i.Type == CodecType.VideoAudioCodec && i.ContainsCodec(audioCodec))
|
if (string.IsNullOrEmpty(audioCodec) || profile.CodecProfiles.Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
|
||||||
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
|
.All(i => AreConditionsSatisfied(i.Conditions, item.Path, videoStream, audioStream)))
|
||||||
{
|
{
|
||||||
playlistItem.Transcode = false;
|
playlistItem.Transcode = false;
|
||||||
|
@ -143,14 +143,14 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
|
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
|
||||||
|
|
||||||
var videoTranscodingConditions = profile.CodecProfiles
|
var videoTranscodingConditions = profile.CodecProfiles
|
||||||
.Where(i => i.Type == CodecType.VideoCodec && i.ContainsCodec(transcodingProfile.VideoCodec))
|
.Where(i => i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
|
||||||
.Take(1)
|
.Take(1)
|
||||||
.SelectMany(i => i.Conditions);
|
.SelectMany(i => i.Conditions);
|
||||||
|
|
||||||
ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
|
ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
|
||||||
|
|
||||||
var audioTranscodingConditions = profile.CodecProfiles
|
var audioTranscodingConditions = profile.CodecProfiles
|
||||||
.Where(i => i.Type == CodecType.VideoAudioCodec && i.ContainsCodec(transcodingProfile.AudioCodec))
|
.Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
||||||
.Take(1)
|
.Take(1)
|
||||||
.SelectMany(i => i.Conditions);
|
.SelectMany(i => i.Conditions);
|
||||||
|
|
||||||
|
@ -162,7 +162,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
private void ApplyTranscodingConditions(PlaylistItem item, IEnumerable<ProfileCondition> conditions)
|
private void ApplyTranscodingConditions(PlaylistItem item, IEnumerable<ProfileCondition> conditions)
|
||||||
{
|
{
|
||||||
foreach (var condition in conditions.Where(i => !string.IsNullOrEmpty(i.Value)))
|
foreach (var condition in conditions
|
||||||
|
.Where(i => !string.IsNullOrEmpty(i.Value)))
|
||||||
{
|
{
|
||||||
var value = condition.Value;
|
var value = condition.Value;
|
||||||
|
|
||||||
|
@ -170,7 +171,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
case ProfileConditionValue.AudioBitrate:
|
case ProfileConditionValue.AudioBitrate:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.AudioBitrate = num;
|
item.AudioBitrate = num;
|
||||||
|
@ -179,7 +180,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.AudioChannels:
|
case ProfileConditionValue.AudioChannels:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.MaxAudioChannels = num;
|
item.MaxAudioChannels = num;
|
||||||
|
@ -190,16 +191,14 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
case ProfileConditionValue.AudioProfile:
|
case ProfileConditionValue.AudioProfile:
|
||||||
case ProfileConditionValue.Has64BitOffsets:
|
case ProfileConditionValue.Has64BitOffsets:
|
||||||
case ProfileConditionValue.VideoBitDepth:
|
case ProfileConditionValue.VideoBitDepth:
|
||||||
case ProfileConditionValue.VideoPacketLength:
|
|
||||||
case ProfileConditionValue.VideoProfile:
|
case ProfileConditionValue.VideoProfile:
|
||||||
case ProfileConditionValue.VideoTimestamp:
|
|
||||||
{
|
{
|
||||||
// Not supported yet
|
// Not supported yet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.Height:
|
case ProfileConditionValue.Height:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.MaxHeight = num;
|
item.MaxHeight = num;
|
||||||
|
@ -208,7 +207,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.VideoBitrate:
|
case ProfileConditionValue.VideoBitrate:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.VideoBitrate = num;
|
item.VideoBitrate = num;
|
||||||
|
@ -217,7 +216,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.VideoFramerate:
|
case ProfileConditionValue.VideoFramerate:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.MaxFramerate = num;
|
item.MaxFramerate = num;
|
||||||
|
@ -226,7 +225,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.VideoLevel:
|
case ProfileConditionValue.VideoLevel:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.VideoLevel = num;
|
item.VideoLevel = num;
|
||||||
|
@ -235,7 +234,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.Width:
|
case ProfileConditionValue.Width:
|
||||||
{
|
{
|
||||||
var num = 0;
|
int num;
|
||||||
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
if (int.TryParse(value, NumberStyles.Any, _usCulture, out num))
|
||||||
{
|
{
|
||||||
item.MaxWidth = num;
|
item.MaxWidth = num;
|
||||||
|
@ -460,12 +459,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
return videoStream == null ? null : videoStream.Width;
|
return videoStream == null ? null : videoStream.Width;
|
||||||
case ProfileConditionValue.VideoLevel:
|
case ProfileConditionValue.VideoLevel:
|
||||||
return videoStream == null ? null : ConvertToLong(videoStream.Level);
|
return videoStream == null ? null : ConvertToLong(videoStream.Level);
|
||||||
case ProfileConditionValue.VideoPacketLength:
|
|
||||||
// TODO: Determine how to get this
|
|
||||||
return null;
|
|
||||||
case ProfileConditionValue.VideoTimestamp:
|
|
||||||
// TODO: Determine how to get this
|
|
||||||
return null;
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException("Unexpected Property");
|
throw new InvalidOperationException("Unexpected Property");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
@ -14,8 +13,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
|
private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
|
||||||
private const string FriendlyName = "MediaBrowser";
|
private const string FriendlyName = "MediaBrowser";
|
||||||
|
|
||||||
private static readonly CookieContainer Container = new CookieContainer();
|
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
|
@ -25,13 +22,17 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<XDocument> SendCommandAsync(string baseUrl, DeviceService service, string command, string postData, string header = null)
|
public async Task<XDocument> SendCommandAsync(string baseUrl,
|
||||||
|
DeviceService service,
|
||||||
|
string command,
|
||||||
|
string postData,
|
||||||
|
string header = null)
|
||||||
{
|
{
|
||||||
var serviceUrl = service.ControlUrl;
|
var serviceUrl = service.ControlUrl;
|
||||||
if (!serviceUrl.StartsWith("/"))
|
if (!serviceUrl.StartsWith("/"))
|
||||||
serviceUrl = "/" + serviceUrl;
|
serviceUrl = "/" + serviceUrl;
|
||||||
|
|
||||||
var response = await PostSoapDataAsync(new Uri(baseUrl + serviceUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header)
|
var response = await PostSoapDataAsync(baseUrl + serviceUrl, "\"" + service.ServiceType + "#" + command + "\"", postData, header)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
|
@ -43,11 +44,16 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SubscribeAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 3600)
|
public async Task SubscribeAsync(string url,
|
||||||
|
string ip,
|
||||||
|
int port,
|
||||||
|
string localIp,
|
||||||
|
int eventport,
|
||||||
|
int timeOut = 3600)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url.ToString(),
|
Url = url,
|
||||||
UserAgent = USERAGENT,
|
UserAgent = USERAGENT,
|
||||||
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
||||||
};
|
};
|
||||||
|
@ -56,14 +62,17 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
|
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
|
||||||
options.RequestHeaders["NT"] = "upnp:event";
|
options.RequestHeaders["NT"] = "upnp:event";
|
||||||
options.RequestHeaders["TIMEOUT"] = "Second - " + timeOut;
|
options.RequestHeaders["TIMEOUT"] = "Second - " + timeOut;
|
||||||
//request.CookieContainer = Container;
|
|
||||||
|
|
||||||
using (await _httpClient.Get(options).ConfigureAwait(false))
|
using (await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RespondAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 20000)
|
public async Task RespondAsync(Uri url,
|
||||||
|
string ip,
|
||||||
|
int port,
|
||||||
|
string localIp,
|
||||||
|
int eventport)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
|
@ -75,24 +84,22 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
|
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport + ">";
|
||||||
options.RequestHeaders["NT"] = "upnp:event";
|
options.RequestHeaders["NT"] = "upnp:event";
|
||||||
options.RequestHeaders["TIMEOUT"] = "Second - 3600";
|
options.RequestHeaders["TIMEOUT"] = "Second - 3600";
|
||||||
//request.CookieContainer = Container;
|
|
||||||
|
|
||||||
using (await _httpClient.Get(options).ConfigureAwait(false))
|
using (await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<XDocument> GetDataAsync(Uri url)
|
public async Task<XDocument> GetDataAsync(string url)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url.ToString(),
|
Url = url,
|
||||||
UserAgent = USERAGENT,
|
UserAgent = USERAGENT,
|
||||||
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
||||||
};
|
};
|
||||||
|
|
||||||
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
||||||
//request.CookieContainer = Container;
|
|
||||||
|
|
||||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -103,14 +110,17 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<HttpResponseInfo> PostSoapDataAsync(Uri url, string soapAction, string postData, string header = null, int timeOut = 20000)
|
private Task<HttpResponseInfo> PostSoapDataAsync(string url,
|
||||||
|
string soapAction,
|
||||||
|
string postData,
|
||||||
|
string header = null)
|
||||||
{
|
{
|
||||||
if (!soapAction.StartsWith("\""))
|
if (!soapAction.StartsWith("\""))
|
||||||
soapAction = "\"" + soapAction + "\"";
|
soapAction = "\"" + soapAction + "\"";
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url.ToString(),
|
Url = url,
|
||||||
UserAgent = USERAGENT,
|
UserAgent = USERAGENT,
|
||||||
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.PlayTo
|
namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
@ -43,15 +41,11 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static string BuildDlnaUrl(DeviceInfo deviceProperties, PlaylistItem item)
|
private static string BuildDlnaUrl(DeviceInfo deviceProperties, PlaylistItem item)
|
||||||
{
|
{
|
||||||
var profile = item.TranscodingSettings.Where(i => i.Name == TranscodingSettingType.VideoProfile)
|
|
||||||
.Select(i => i.Value)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
var usCulture = new CultureInfo("en-US");
|
var usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
var list = new List<string>
|
var list = new List<string>
|
||||||
{
|
{
|
||||||
item.DeviceProfileName ?? string.Empty,
|
item.DeviceProfileId ?? string.Empty,
|
||||||
deviceProperties.UUID ?? string.Empty,
|
deviceProperties.UUID ?? string.Empty,
|
||||||
item.MediaSourceId ?? string.Empty,
|
item.MediaSourceId ?? string.Empty,
|
||||||
(!item.Transcode).ToString().ToLower(),
|
(!item.Transcode).ToString().ToLower(),
|
||||||
|
@ -66,7 +60,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(usCulture) : string.Empty,
|
item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(usCulture) : string.Empty,
|
||||||
item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(usCulture) : string.Empty,
|
item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(usCulture) : string.Empty,
|
||||||
item.StartPositionTicks.ToString(usCulture),
|
item.StartPositionTicks.ToString(usCulture),
|
||||||
profile ?? string.Empty,
|
|
||||||
item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(usCulture) : string.Empty
|
item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(usCulture) : string.Empty
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class DefaultProfile : DeviceProfile
|
public class DefaultProfile : DeviceProfile
|
||||||
{
|
{
|
||||||
public DefaultProfile()
|
public DefaultProfile()
|
||||||
{
|
{
|
||||||
|
Name = "Generic Device";
|
||||||
|
|
||||||
ProtocolInfo = "DLNA";
|
ProtocolInfo = "DLNA";
|
||||||
|
|
||||||
ClientType = "DLNA";
|
FriendlyName = "Media Browser";
|
||||||
Manufacturer = "Media Browser";
|
Manufacturer = "Media Browser";
|
||||||
ModelDescription = "Media Browser";
|
ModelDescription = "Media Browser";
|
||||||
ModelName = "Media Browser";
|
ModelName = "Media Browser";
|
||||||
|
@ -53,24 +57,6 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CodecProfiles = new[]
|
|
||||||
{
|
|
||||||
new CodecProfile
|
|
||||||
{
|
|
||||||
Type = CodecType.VideoCodec,
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition
|
|
||||||
{
|
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
|
||||||
Property = ProfileConditionValue.VideoLevel,
|
|
||||||
Value = "3",
|
|
||||||
IsRequired = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class DenonAvrProfile : DefaultProfile
|
public class DenonAvrProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public DenonAvrProfile()
|
public DenonAvrProfile()
|
||||||
|
|
31
MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
Normal file
31
MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class LgTvProfile : DefaultProfile
|
public class LgTvProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public LgTvProfile()
|
public LgTvProfile()
|
||||||
|
@ -111,7 +113,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg4",
|
Codec = "mpeg4",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -139,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -173,7 +175,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3,aac,mp3",
|
Codec = "ac3,aac,mp3",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class LinksysDMA2100Profile : DefaultProfile
|
public class LinksysDMA2100Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public LinksysDMA2100Profile()
|
public LinksysDMA2100Profile()
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
public class PanasonicVieraProfile : DefaultProfile
|
[XmlRoot("Profile")]
|
||||||
|
public class PanasonicVieraProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public PanasonicVieraProfile()
|
public PanasonicVieraProfile()
|
||||||
{
|
{
|
||||||
Name = "Panasonic Viera";
|
Name = "Panasonic Viera";
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
FriendlyName = @"VIERA",
|
FriendlyName = @"VIERA",
|
||||||
Manufacturer = "Panasonic",
|
Manufacturer = "Panasonic",
|
||||||
|
|
||||||
Headers = new[]
|
Headers = new[]
|
||||||
{
|
{
|
||||||
new HttpHeaderInfo
|
new HttpHeaderInfo
|
||||||
{
|
{
|
||||||
|
@ -22,11 +24,11 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
Match = HeaderMatchType.Substring
|
Match = HeaderMatchType.Substring
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TimelineOffsetSeconds = 10;
|
TimelineOffsetSeconds = 10;
|
||||||
|
|
||||||
TranscodingProfiles = new[]
|
TranscodingProfiles = new[]
|
||||||
{
|
{
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
|
@ -48,7 +50,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DirectPlayProfiles = new[]
|
DirectPlayProfiles = new[]
|
||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
|
@ -127,7 +129,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ContainerProfiles = new[]
|
ContainerProfiles = new[]
|
||||||
{
|
{
|
||||||
new ContainerProfile
|
new ContainerProfile
|
||||||
{
|
{
|
||||||
|
@ -151,11 +153,11 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CodecProfiles = new[]
|
CodecProfiles = new[]
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
{
|
{
|
||||||
|
@ -181,6 +183,6 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SamsungSmartTvProfile : DefaultProfile
|
public class SamsungSmartTvProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SamsungSmartTvProfile()
|
public SamsungSmartTvProfile()
|
||||||
{
|
{
|
||||||
Name = "Samsung Smart TV";
|
Name = "Samsung Smart TV";
|
||||||
|
|
||||||
SupportsAlbumArtInDidl = true;
|
EnableAlbumArtInDidl = true;
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
|
@ -143,7 +145,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg2video",
|
Codec = "mpeg2video",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -177,7 +179,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg4",
|
Codec = "mpeg4",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -211,7 +213,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -251,7 +253,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "wmv2,wmv3,vc1",
|
Codec = "wmv2,wmv3,vc1",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -285,7 +287,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3,wmav2,dca,aac,mp3",
|
Codec = "ac3,wmav2,dca,aac,mp3",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
@ -302,6 +304,13 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
MediaProfiles = new[]
|
MediaProfiles = new[]
|
||||||
{
|
{
|
||||||
|
new MediaProfile
|
||||||
|
{
|
||||||
|
Container = "avi",
|
||||||
|
MimeType = "video/x-msvideo",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
{
|
{
|
||||||
Container = "mkv",
|
Container = "mkv",
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBlurayPlayer2013Profile : DefaultProfile
|
public class SonyBlurayPlayer2013Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBlurayPlayer2013Profile()
|
public SonyBlurayPlayer2013Profile()
|
||||||
{
|
{
|
||||||
|
Name = "Sony Blu-ray Player 2013";
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
FriendlyName = @"Blu-ray Disc Player",
|
FriendlyName = @"Blu-ray Disc Player",
|
||||||
|
@ -109,7 +113,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -137,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBlurayPlayerProfile : DefaultProfile
|
public class SonyBlurayPlayerProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBlurayPlayerProfile()
|
public SonyBlurayPlayerProfile()
|
||||||
{
|
{
|
||||||
|
Name = "Sony Blu-ray Player";
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
FriendlyName = @"Blu-ray Disc Player",
|
FriendlyName = @"Blu-ray Disc Player",
|
||||||
|
@ -105,7 +109,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -147,7 +151,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -163,7 +167,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBravia2010Profile : DefaultProfile
|
public class SonyBravia2010Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBravia2010Profile()
|
public SonyBravia2010Profile()
|
||||||
|
@ -96,13 +98,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/vnd.dlna.mpeg-tts",
|
MimeType = "video/vnd.dlna.mpeg-tts",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -112,12 +108,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -177,7 +168,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
|
@ -197,7 +188,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -224,7 +215,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg2video",
|
Codec = "mpeg2video",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -245,7 +236,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -261,7 +252,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBravia2011Profile : DefaultProfile
|
public class SonyBravia2011Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBravia2011Profile()
|
public SonyBravia2011Profile()
|
||||||
|
@ -138,13 +140,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/vnd.dlna.mpeg-tts",
|
MimeType = "video/vnd.dlna.mpeg-tts",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -154,12 +150,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -195,7 +186,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
|
@ -215,7 +206,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -242,7 +233,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg2video",
|
Codec = "mpeg2video",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -263,7 +254,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -279,7 +270,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBravia2012Profile : DefaultProfile
|
public class SonyBravia2012Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBravia2012Profile()
|
public SonyBravia2012Profile()
|
||||||
|
@ -126,13 +128,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/vnd.dlna.mpeg-tts",
|
MimeType = "video/vnd.dlna.mpeg-tts",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -142,12 +138,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -207,7 +198,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
{
|
{
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
|
@ -227,7 +218,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyBravia2013Profile : DefaultProfile
|
public class SonyBravia2013Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyBravia2013Profile()
|
public SonyBravia2013Profile()
|
||||||
|
@ -182,13 +184,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/vnd.dlna.mpeg-tts",
|
MimeType = "video/vnd.dlna.mpeg-tts",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -198,12 +194,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
AudioCodec="ac3,aac,mp3",
|
AudioCodec="ac3,aac,mp3",
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video
|
||||||
|
|
||||||
Conditions = new []
|
|
||||||
{
|
|
||||||
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new MediaProfile
|
new MediaProfile
|
||||||
|
@ -240,7 +231,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class SonyPs3Profile : DefaultProfile
|
public class SonyPs3Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public SonyPs3Profile()
|
public SonyPs3Profile()
|
||||||
|
@ -83,7 +85,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -126,7 +128,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3",
|
Codec = "ac3",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -151,7 +153,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "wmapro",
|
Codec = "wmapro",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -167,7 +169,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -184,7 +186,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class WdtvLiveProfile : DefaultProfile
|
public class WdtvLiveProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public WdtvLiveProfile()
|
public WdtvLiveProfile()
|
||||||
|
@ -193,7 +195,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
@ -221,7 +223,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
|
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class Xbox360Profile : DefaultProfile
|
public class Xbox360Profile : DefaultProfile
|
||||||
{
|
{
|
||||||
public Xbox360Profile()
|
public Xbox360Profile()
|
||||||
|
@ -163,7 +165,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "mpeg4",
|
Codec = "mpeg4",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -198,7 +200,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "h264",
|
Codec = "h264",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -227,20 +229,13 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
Property = ProfileConditionValue.VideoBitrate,
|
Property = ProfileConditionValue.VideoBitrate,
|
||||||
Value = "10240000",
|
Value = "10240000",
|
||||||
IsRequired = false
|
IsRequired = false
|
||||||
},
|
|
||||||
new ProfileCondition
|
|
||||||
{
|
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
|
||||||
Property = ProfileConditionValue.VideoLevel,
|
|
||||||
Value = "3",
|
|
||||||
IsRequired = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoCodec,
|
Type = CodecType.Video,
|
||||||
Codec = "wmv2,wmv3,vc1",
|
Codec = "wmv2,wmv3,vc1",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -269,20 +264,13 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
Property = ProfileConditionValue.VideoBitrate,
|
Property = ProfileConditionValue.VideoBitrate,
|
||||||
Value = "15360000",
|
Value = "15360000",
|
||||||
IsRequired = false
|
IsRequired = false
|
||||||
},
|
|
||||||
new ProfileCondition
|
|
||||||
{
|
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
|
||||||
Property = ProfileConditionValue.VideoLevel,
|
|
||||||
Value = "3",
|
|
||||||
IsRequired = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "ac3,wmav2,wmapro",
|
Codec = "ac3,wmav2,wmapro",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
@ -298,7 +286,7 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
|
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudioCodec,
|
Type = CodecType.VideoAudio,
|
||||||
Codec = "aac",
|
Codec = "aac",
|
||||||
Conditions = new []
|
Conditions = new []
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
public class XboxOneProfile : DefaultProfile
|
public class XboxOneProfile : DefaultProfile
|
||||||
{
|
{
|
||||||
public XboxOneProfile()
|
public XboxOneProfile()
|
||||||
|
|
35
MediaBrowser.Dlna/Profiles/Xml/Default.xml
Normal file
35
MediaBrowser.Dlna/Profiles/Xml/Default.xml
Normal 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>
|
39
MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
Normal file
39
MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
Normal 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>
|
73
MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
Normal file
73
MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
Normal 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>
|
39
MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
Normal file
39
MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
Normal 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>
|
66
MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
Normal file
66
MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
Normal 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>
|
102
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
Normal file
102
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
Normal 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>
|
69
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
Normal file
69
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
Normal file
File diff suppressed because one or more lines are too long
97
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
Normal file
97
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
Normal file
File diff suppressed because one or more lines are too long
100
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
Normal file
100
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
Normal 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>
|
103
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
Normal file
103
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
Normal 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>
|
86
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
Normal file
86
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
Normal 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>
|
86
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
Normal file
86
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
Normal 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>
|
94
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
Normal file
94
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
Normal 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>
|
80
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
Normal file
80
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
Normal 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>
|
103
MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
Normal file
103
MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
Normal 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>
|
41
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
Normal file
41
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
Normal 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>
|
41
MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
Normal file
41
MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
Normal 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>
|
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Dlna.Server
|
||||||
private readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
|
private readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
|
||||||
private readonly static Regex Validator = new Regex(@"^[a-z\d][a-z\d_.-]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly static Regex Validator = new Regex(@"^[a-z\d][a-z\d_.-]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
protected Headers(bool asIs)
|
public Headers(bool asIs)
|
||||||
{
|
{
|
||||||
_asIs = asIs;
|
_asIs = asIs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -96,7 +96,7 @@ namespace MediaBrowser.Dlna.Server
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var parts = line.Split(new char[] { ':' }, 2);
|
var parts = line.Split(new[] { ':' }, 2);
|
||||||
headers[parts[0]] = parts[1].Trim();
|
headers[parts[0]] = parts[1].Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace MediaBrowser.Dlna.Server
|
||||||
|
|
||||||
private void SendSearchResponse(IPEndPoint endpoint, UpnpDevice dev)
|
private void SendSearchResponse(IPEndPoint endpoint, UpnpDevice dev)
|
||||||
{
|
{
|
||||||
var headers = new RawHeaders();
|
var headers = new Headers(true);
|
||||||
headers.Add("CACHE-CONTROL", "max-age = 600");
|
headers.Add("CACHE-CONTROL", "max-age = 600");
|
||||||
headers.Add("DATE", DateTime.Now.ToString("R"));
|
headers.Add("DATE", DateTime.Now.ToString("R"));
|
||||||
headers.Add("EXT", "");
|
headers.Add("EXT", "");
|
||||||
|
@ -188,7 +188,7 @@ namespace MediaBrowser.Dlna.Server
|
||||||
private void NotifyDevice(UpnpDevice dev, string type, bool sticky)
|
private void NotifyDevice(UpnpDevice dev, string type, bool sticky)
|
||||||
{
|
{
|
||||||
_logger.Debug("NotifyDevice");
|
_logger.Debug("NotifyDevice");
|
||||||
var headers = new RawHeaders();
|
var headers = new Headers(true);
|
||||||
headers.Add("HOST", "239.255.255.250:1900");
|
headers.Add("HOST", "239.255.255.250:1900");
|
||||||
headers.Add("CACHE-CONTROL", "max-age = 600");
|
headers.Add("CACHE-CONTROL", "max-age = 600");
|
||||||
headers.Add("LOCATION", dev.Descriptor.ToString());
|
headers.Add("LOCATION", dev.Descriptor.ToString());
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.PlayTo
|
namespace MediaBrowser.Dlna.Ssdp
|
||||||
{
|
{
|
||||||
public class SsdpHelper
|
public class SsdpHelper
|
||||||
{
|
{
|
||||||
|
@ -29,28 +30,29 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">The data.</param>
|
/// <param name="data">The data.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Uri ParseSsdpResponse(string data)
|
public static Dictionary<string,string> ParseSsdpResponse(byte[] data)
|
||||||
{
|
{
|
||||||
var res = (from line in data.Split(new[] { '\r', '\n' })
|
var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
where line.ToLowerInvariant().StartsWith("location:")
|
|
||||||
select line).FirstOrDefault();
|
|
||||||
|
|
||||||
return !string.IsNullOrEmpty(res) ? new Uri(res.Substring(9).Trim()) : null;
|
using (var reader = new StreamReader(new MemoryStream(data), Encoding.ASCII))
|
||||||
}
|
{
|
||||||
|
for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
|
||||||
|
{
|
||||||
|
line = line.Trim();
|
||||||
|
if (string.IsNullOrEmpty(line))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var parts = line.Split(new[] { ':' }, 2);
|
||||||
|
|
||||||
/// <summary>
|
if (parts.Length == 2)
|
||||||
/// Parses data into SSDP event.
|
{
|
||||||
/// </summary>
|
headers[parts[0]] = parts[1].Trim();
|
||||||
/// <param name="data">The data.</param>
|
}
|
||||||
/// <returns></returns>
|
}
|
||||||
[Obsolete("Not yet used", true)]
|
}
|
||||||
public static string ParseSsdpEvent(string data)
|
|
||||||
{
|
return headers;
|
||||||
var sid = (from line in data.Split(new[] { '\r', '\n' })
|
|
||||||
where line.ToLowerInvariant().StartsWith("sid:")
|
|
||||||
select line).FirstOrDefault();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.BdInfo
|
namespace MediaBrowser.MediaEncoding.BdInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BdInfoExaminer
|
/// Class BdInfoExaminer
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue