diff options
33 files changed, 980 insertions, 680 deletions
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index a32a1ad03..62596287e 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; @@ -67,6 +68,18 @@ namespace MediaBrowser.Api { } + [Route("/Items/RemoteSearch/MusicArtist", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/MusicAlbum", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>> + { + } + [Route("/Items/RemoteSearch/Person", "POST")] [Api(Description = "Gets external id infos for an item")] public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>> @@ -167,6 +180,20 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } + public object Post(GetMusicAlbumRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetMusicArtistRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + public object Get(GetRemoteSearchImage request) { var result = GetRemoteImage(request).Result; diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index ca9214b54..ac9a51ea1 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -259,7 +259,10 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true }; } - _logger.Info("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url); + if (options.LogRequest) + { + _logger.Info("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url); + } try { @@ -456,7 +459,10 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager options.Progress.Report(0); - _logger.Info("HttpClientManager.GetTempFileResponse url: {0}", options.Url); + if (options.LogRequest) + { + _logger.Info("HttpClientManager.GetTempFileResponse url: {0}", options.Url); + } try { diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs index 659d230cf..da0449ae7 100644 --- a/MediaBrowser.Common/Net/HttpRequestOptions.cs +++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs @@ -72,6 +72,8 @@ namespace MediaBrowser.Common.Net public bool BufferContent { get; set; } + public bool LogRequest { get; set; } + public HttpRequestCachePolicy CachePolicy { get; set; } private string GetHeaderValue(string name) @@ -94,6 +96,8 @@ namespace MediaBrowser.Common.Net CachePolicy = HttpRequestCachePolicy.None; RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + + LogRequest = true; } } diff --git a/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs b/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs new file mode 100644 index 000000000..f1922dd32 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs @@ -0,0 +1,25 @@ + +namespace MediaBrowser.Controller.Dlna +{ + public class DirectPlayProfile + { + public string[] Containers { get; set; } + public string[] AudioCodecs { get; set; } + public string[] VideoCodecs { get; set; } + public string MimeType { get; set; } + public DlnaProfileType Type { get; set; } + + public DirectPlayProfile() + { + Containers = new string[] { }; + AudioCodecs = new string[] { }; + VideoCodecs = new string[] { }; + } + } + + public enum DlnaProfileType + { + Audio = 0, + Video = 1 + } +} diff --git a/MediaBrowser.Controller/Dlna/DlnaProfile.cs b/MediaBrowser.Controller/Dlna/DlnaProfile.cs new file mode 100644 index 000000000..33f95b794 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/DlnaProfile.cs @@ -0,0 +1,54 @@ + +namespace MediaBrowser.Controller.Dlna +{ + public class DlnaProfile + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } + + /// <summary> + /// Gets or sets the type of the client. + /// </summary> + /// <value>The type of the client.</value> + public string ClientType { get; set; } + + /// <summary> + /// Gets or sets the name of the friendly. + /// </summary> + /// <value>The name of the friendly.</value> + public string FriendlyName { get; set; } + + /// <summary> + /// Gets or sets the model number. + /// </summary> + /// <value>The model number.</value> + public string ModelNumber { get; set; } + + /// <summary> + /// Gets or sets the name of the model. + /// </summary> + /// <value>The name of the model.</value> + public string ModelName { get; set; } + + /// <summary> + /// Gets or sets the transcoding profiles. + /// </summary> + /// <value>The transcoding profiles.</value> + public TranscodingProfile[] TranscodingProfiles { get; set; } + + /// <summary> + /// Gets or sets the direct play profiles. + /// </summary> + /// <value>The direct play profiles.</value> + public DirectPlayProfile[] DirectPlayProfiles { get; set; } + + public DlnaProfile() + { + DirectPlayProfiles = new DirectPlayProfile[] { }; + TranscodingProfiles = new TranscodingProfile[] { }; + } + } +} diff --git a/MediaBrowser.Controller/Dlna/IDlnaManager.cs b/MediaBrowser.Controller/Dlna/IDlnaManager.cs new file mode 100644 index 000000000..017dbc874 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/IDlnaManager.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Dlna +{ + public interface IDlnaManager + { + /// <summary> + /// Gets the dlna profiles. + /// </summary> + /// <returns>IEnumerable{DlnaProfile}.</returns> + IEnumerable<DlnaProfile> GetProfiles(); + + /// <summary> + /// Gets the default profile. + /// </summary> + /// <returns>DlnaProfile.</returns> + DlnaProfile GetDefaultProfile(); + + /// <summary> + /// Gets the profile. + /// </summary> + /// <param name="friendlyName">Name of the friendly.</param> + /// <param name="modelName">Name of the model.</param> + /// <param name="modelNumber">The model number.</param> + /// <returns>DlnaProfile.</returns> + DlnaProfile GetProfile(string friendlyName, string modelName, string modelNumber); + } +} diff --git a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs new file mode 100644 index 000000000..abc8868fb --- /dev/null +++ b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs @@ -0,0 +1,16 @@ + +namespace MediaBrowser.Controller.Dlna +{ + public class TranscodingProfile + { + public string Container { get; set; } + + public DlnaProfileType Type { get; set; } + + public string MimeType { get; set; } + + public string VideoCodec { get; set; } + + public string AudioCodec { get; set; } + } +} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 23f8ac31a..e0c792307 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1332,6 +1332,11 @@ namespace MediaBrowser.Controller.Entities return ImageInfos.Where(i => i.Type == imageType); } + public bool AddImages(ImageType imageType, IEnumerable<FileInfo> images) + { + return AddImages(imageType, images.Cast<FileSystemInfo>()); + } + /// <summary> /// Adds the images. /// </summary> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 16c54861e..21a501b08 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -73,6 +73,10 @@ <Compile Include="Channels\IChannelManager.cs" /> <Compile Include="Collections\CollectionCreationOptions.cs" /> <Compile Include="Collections\ICollectionManager.cs" /> + <Compile Include="Dlna\DirectPlayProfile.cs" /> + <Compile Include="Dlna\IDlnaManager.cs" /> + <Compile Include="Dlna\DlnaProfile.cs" /> + <Compile Include="Dlna\TranscodingProfile.cs" /> <Compile Include="Drawing\IImageProcessor.cs" /> <Compile Include="Drawing\ImageFormat.cs" /> <Compile Include="Drawing\ImageProcessingOptions.cs" /> diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs new file mode 100644 index 000000000..1c9cba2be --- /dev/null +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -0,0 +1,376 @@ +using MediaBrowser.Controller.Dlna; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace MediaBrowser.Dlna +{ + public class DlnaManager : IDlnaManager + { + public IEnumerable<DlnaProfile> GetProfiles() + { + var list = new List<DlnaProfile>(); + + list.Add(new DlnaProfile + { + Name = "Samsung TV (B Series)", + ClientType = "DLNA", + FriendlyName = "^TV$", + ModelNumber = @"1\.0", + ModelName = "Samsung DTV DMR", + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + MimeType = "x-msvideo", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"mp4"}, + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + Name = "Samsung TV (E/F-series)", + ClientType = "DLNA", + FriendlyName = @"(^\[TV\][A-Z]{2}\d{2}(E|F)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung", + ModelNumber = @"(1\.0)|(AllShare1\.0)", + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + MimeType = "x-msvideo", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"mp4"}, + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + Name = "Samsung TV (C/D-series)", + ClientType = "DLNA", + FriendlyName = @"(^TV-\d{2}C\d{3}.*)|(^\[TV\][A-Z]{2}\d{2}(D)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung", + ModelNumber = @"(1\.0)|(AllShare1\.0)", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + MimeType = "x-msvideo", + Type = DlnaProfileType.Video + }, + new DirectPlayProfile + { + Containers = new[]{"mp4"}, + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + Name = "Xbox 360", + ClientType = "DLNA", + ModelName = "Xbox 360", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + MimeType = "x-msvideo", + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + Name = "Xbox One", + ModelName = "Xbox One", + ClientType = "DLNA", + FriendlyName = "Xbox-SystemOS", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + MimeType = "x-msvideo", + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + Name = "Sony Bravia (2012)", + ClientType = "DLNA", + FriendlyName = @"BRAVIA KDL-\d{2}[A-Z]X\d5(\d|G).*", + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3"}, + Type = DlnaProfileType.Audio + }, + new DirectPlayProfile + { + Containers = new[]{"avi"}, + Type = DlnaProfileType.Video, + MimeType = "avi" + } + } + }); + + //WDTV does not need any transcoding of the formats we support statically + list.Add(new DlnaProfile + { + Name = "WDTV Live", + ClientType = "DLNA", + ModelName = "WD TV HD Live", + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3", "flac", "m4a", "wma"}, + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Containers = new[]{"avi", "mp4", "mkv", "ts"}, + Type = DlnaProfileType.Video + } + } + }); + + list.Add(new DlnaProfile + { + //Linksys DMA2100us does not need any transcoding of the formats we support statically + Name = "Linksys DMA2100", + ClientType = "DLNA", + ModelName = "DMA2100us", + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3", "flac", "m4a", "wma"}, + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Containers = new[]{"avi", "mp4", "mkv", "ts"}, + Type = DlnaProfileType.Video + } + } + }); + + return list; + } + + public DlnaProfile GetDefaultProfile() + { + return new DlnaProfile + { + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mp3", "wma"}, + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Containers = new[]{"avi", "mp4"}, + Type = DlnaProfileType.Video + } + } + }; + } + + public DlnaProfile GetProfile(string friendlyName, string modelName, string modelNumber) + { + foreach (var profile in GetProfiles()) + { + if (!string.IsNullOrEmpty(profile.FriendlyName)) + { + if (!Regex.IsMatch(friendlyName, profile.FriendlyName)) + continue; + } + + if (!string.IsNullOrEmpty(profile.ModelNumber)) + { + if (!Regex.IsMatch(modelNumber, profile.ModelNumber)) + continue; + } + + if (!string.IsNullOrEmpty(profile.ModelName)) + { + if (!Regex.IsMatch(modelName, profile.ModelName)) + continue; + } + + return profile; + + } + return GetDefaultProfile(); + } + } +}
\ No newline at end of file diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 622ccefbc..a7ee05cf3 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -51,15 +51,14 @@ <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> + <Compile Include="DlnaManager.cs" /> <Compile Include="PlayTo\Argument.cs" /> - <Compile Include="PlayTo\Configuration\DlnaProfile.cs" /> - <Compile Include="PlayTo\Configuration\PlayToConfiguration.cs" /> - <Compile Include="PlayTo\Configuration\TranscodeSetting.cs" /> <Compile Include="PlayTo\CurrentIdEventArgs.cs" /> <Compile Include="PlayTo\Device.cs"> <SubType>Code</SubType> </Compile> - <Compile Include="PlayTo\DeviceProperties.cs" /> + <Compile Include="PlayTo\DeviceInfo.cs" /> + <Compile Include="PlayTo\DeviceService.cs" /> <Compile Include="PlayTo\DidlBuilder.cs" /> <Compile Include="PlayTo\DlnaController.cs" /> <Compile Include="PlayTo\DlnaControllerFactory.cs" /> @@ -81,7 +80,6 @@ <Compile Include="PlayTo\uIcon.cs" /> <Compile Include="PlayTo\uParser.cs" /> <Compile Include="PlayTo\uPnpNamespaces.cs" /> - <Compile Include="PlayTo\uService.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> @@ -98,6 +96,9 @@ <Name>MediaBrowser.Model</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <Folder Include="Server\" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs b/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs deleted file mode 100644 index e75cea5a9..000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class DlnaProfile - { - /// <summary> - /// Gets or sets the name to be displayed. - /// </summary> - /// <value> - /// The name. - /// </value> - public string Name { get; set; } - - /// <summary> - /// Gets or sets the type of the client. - /// </summary> - /// <value> - /// The type of the client. - /// </value> - public string ClientType { get; set; } - - /// <summary> - /// Gets or sets the name of the friendly. - /// </summary> - /// <value> - /// The name of the friendly. - /// </value> - public string FriendlyName { get; set; } - - /// <summary> - /// Gets or sets the model number. - /// </summary> - /// <value> - /// The model number. - /// </value> - public string ModelNumber { get; set; } - - /// <summary> - /// Gets or sets the name of the model. - /// </summary> - /// <value> - /// The name of the model. - /// </value> - public string ModelName { get; set; } - - /// <summary> - /// Gets or sets the transcode settings. - /// </summary> - /// <value> - /// The transcode settings. - /// </value> - public TranscodeSettings[] TranscodeSettings { get; set; } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs b/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs deleted file mode 100644 index d3fcb24ad..000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs +++ /dev/null @@ -1,134 +0,0 @@ -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class PlayToConfiguration - { - private static readonly string[] _supportedStaticFormats = { "mp3", "flac", "m4a", "wma", "avi", "mp4", "mkv", "ts" }; - public static string[] SupportedStaticFormats - { - get - { - return _supportedStaticFormats; - } - } - - private static readonly DlnaProfile[] _profiles = GetDefaultProfiles(); - public static DlnaProfile[] Profiles - { - get - { - return _profiles; - } - } - - private static DlnaProfile[] GetDefaultProfiles() - { - var profile0 = new DlnaProfile - { - Name = "Samsung TV (B Series) [Profile]", - ClientType = "DLNA", - FriendlyName = "^TV$", - ModelNumber = @"1\.0", - ModelName = "Samsung DTV DMR", - TranscodeSettings = new[] - { - new TranscodeSettings {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSettings {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSettings {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile1 = new DlnaProfile - { - Name = "Samsung TV (E/F-series) [Profile]", - ClientType = "DLNA", - FriendlyName = @"(^\[TV\][A-Z]{2}\d{2}(E|F)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung", - ModelNumber = @"(1\.0)|(AllShare1\.0)", - TranscodeSettings = new[] - { - new TranscodeSettings {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSettings {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSettings {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile2 = new DlnaProfile - { - Name = "Samsung TV (C/D-series) [Profile]", - ClientType = "DLNA", - FriendlyName = @"(^TV-\d{2}C\d{3}.*)|(^\[TV\][A-Z]{2}\d{2}(D)[A-Z]?\d{3,4}.*)|^\[TV\] Samsung", - ModelNumber = @"(1\.0)|(AllShare1\.0)", - TranscodeSettings = new[] - { - new TranscodeSettings {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSettings {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSettings {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile3 = new DlnaProfile - { - Name = "Xbox 360 [Profile]", - ClientType = "DLNA", - ModelName = "Xbox 360", - TranscodeSettings = new[] - { - new TranscodeSettings {Container = "mkv", TargetContainer = "ts"}, - new TranscodeSettings {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSettings {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile4 = new DlnaProfile - { - Name = "Xbox One [Profile]", - ModelName = "Xbox One", - ClientType = "DLNA", - FriendlyName = "Xbox-SystemOS", - TranscodeSettings = new[] - { - new TranscodeSettings {Container = "mkv", TargetContainer = "ts"}, - new TranscodeSettings {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSettings {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile5 = new DlnaProfile - { - Name = "Sony Bravia TV (2012)", - ClientType = "TV", - FriendlyName = @"BRAVIA KDL-\d{2}[A-Z]X\d5(\d|G).*", - TranscodeSettings = TranscodeSettings.GetDefaultTranscodingSettings() - }; - - //WDTV does not need any transcoding of the formats we support statically - var profile6 = new DlnaProfile - { - Name = "WDTV Live [Profile]", - ClientType = "DLNA", - ModelName = "WD TV HD Live", - TranscodeSettings = new TranscodeSettings[] { } - }; - - var profile7 = new DlnaProfile - { - //Linksys DMA2100us does not need any transcoding of the formats we support statically - Name = "Linksys DMA2100 [Profile]", - ClientType = "DLNA", - ModelName = "DMA2100us", - TranscodeSettings = new TranscodeSettings[] { } - }; - - return new[] - { - profile0, - profile1, - profile2, - profile3, - profile4, - profile5, - profile6, - profile7 - }; - } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs b/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs deleted file mode 100644 index 4713dc385..000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class TranscodeSettings - { - /// <summary> - /// Gets or sets the container. - /// </summary> - /// <value> - /// The container. - /// </value> - public string Container { get; set; } - - /// <summary> - /// Gets or sets the target container. - /// </summary> - /// <value> - /// The target container. - /// </value> - public string TargetContainer { get; set; } - - /// <summary> - /// Gets or sets the Mimetype to enforce - /// </summary> - /// <value> - /// The MimeType. - /// </value> - public string MimeType { get; set; } - - /// <summary> - /// The default transcoding settings - /// </summary> - private static readonly TranscodeSettings[] DefaultTranscodingSettings = - { - new TranscodeSettings { Container = "mkv", TargetContainer = "ts" }, - new TranscodeSettings { Container = "flac", TargetContainer = "mp3" }, - new TranscodeSettings { Container = "m4a", TargetContainer = "mp3" } - }; - - public static TranscodeSettings[] GetDefaultTranscodingSettings() - { - return DefaultTranscodingSettings; - } - - /// <summary> - /// Gets the profile settings. - /// </summary> - /// <param name="deviceProperties">The device properties.</param> - /// <returns>The TranscodeSettings for the device</returns> - public static TranscodeSettings[] GetProfileSettings(DeviceProperties deviceProperties) - { - foreach (var profile in PlayToConfiguration.Profiles) - { - if (!string.IsNullOrEmpty(profile.FriendlyName)) - { - if (!Regex.IsMatch(deviceProperties.Name, profile.FriendlyName)) - continue; - } - - if (!string.IsNullOrEmpty(profile.ModelNumber)) - { - if (!Regex.IsMatch(deviceProperties.ModelNumber, profile.ModelNumber)) - continue; - } - - if (!string.IsNullOrEmpty(profile.ModelName)) - { - if (!Regex.IsMatch(deviceProperties.ModelName, profile.ModelName)) - continue; - } - - deviceProperties.DisplayName = profile.Name; - deviceProperties.ClientType = profile.ClientType; - return profile.TranscodeSettings; - - } - - // Since we don't have alot of info about different devices we go down the safe - // route abd use the default transcoding settings if no profile exist - return GetDefaultTranscodingSettings(); - } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index 690f7525b..4120c1a7f 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -9,7 +10,7 @@ using System.Xml.Linq; namespace MediaBrowser.Dlna.PlayTo { - public sealed class Device : IDisposable + public class Device : IDisposable { const string ServiceAvtransportId = "urn:upnp-org:serviceId:AVTransport"; const string ServiceRenderingId = "urn:upnp-org:serviceId:RenderingControl"; @@ -18,7 +19,7 @@ namespace MediaBrowser.Dlna.PlayTo private Timer _timer; - public DeviceProperties Properties { get; set; } + public DeviceInfo Properties { get; set; } private int _muteVol; public bool IsMuted @@ -119,12 +120,14 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IHttpClient _httpClient; private readonly ILogger _logger; + private readonly IServerConfigurationManager _config; - public Device(DeviceProperties deviceProperties, IHttpClient httpClient, ILogger logger) + public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger, IServerConfigurationManager config) { Properties = deviceProperties; _httpClient = httpClient; _logger = logger; + _config = config; } private int GetPlaybackTimerIntervalMs() @@ -217,7 +220,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, value)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, value)) .ConfigureAwait(false); Volume = value; return true; @@ -236,7 +239,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, String.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, String.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) .ConfigureAwait(false); return value; @@ -266,14 +269,13 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, url, dictionary), header) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, url, dictionary), header) .ConfigureAwait(false); - if (!IsPlaying) - { - await Task.Delay(50).ConfigureAwait(false); - await SetPlay().ConfigureAwait(false); - } + + await Task.Delay(50).ConfigureAwait(false); + await SetPlay().ConfigureAwait(false); + _lapsCount = GetLapsCount(); RestartTimer(); @@ -312,7 +314,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, value, dictionary), header) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, value, dictionary), header) .ConfigureAwait(false); await Task.Delay(100).ConfigureAwait(false); @@ -333,7 +335,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 1)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 1)) .ConfigureAwait(false); _lapsCount = GetLapsCount(); @@ -348,9 +350,8 @@ namespace MediaBrowser.Dlna.PlayTo var service = Properties.Services.FirstOrDefault(s => s.ServiceId == ServiceAvtransportId); - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 1)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 1)) .ConfigureAwait(false); - await Task.Delay(50).ConfigureAwait(false); return true; } @@ -363,7 +364,7 @@ namespace MediaBrowser.Dlna.PlayTo var service = Properties.Services.FirstOrDefault(s => s.ServiceId == ServiceAvtransportId); - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 0)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, 0)) .ConfigureAwait(false); await Task.Delay(50).ConfigureAwait(false); @@ -442,7 +443,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -473,7 +474,7 @@ namespace MediaBrowser.Dlna.PlayTo if (service == null) return; - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -503,7 +504,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -544,7 +545,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -599,13 +600,13 @@ namespace MediaBrowser.Dlna.PlayTo if (avService == null) return; - var url = avService.SCPDURL; + var url = avService.ScpdUrl; if (!url.Contains("/")) url = "/dmr/" + url; if (!url.StartsWith("/")) url = "/" + url; - var httpClient = new SsdpHttpClient(_httpClient); + var httpClient = new SsdpHttpClient(_httpClient, _config); var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url)); AvCommands = TransportCommands.Create(document); @@ -617,13 +618,13 @@ namespace MediaBrowser.Dlna.PlayTo if (avService == null) return; - string url = avService.SCPDURL; + string url = avService.ScpdUrl; if (!url.Contains("/")) url = "/dmr/" + url; if (!url.StartsWith("/")) url = "/" + url; - var httpClient = new SsdpHttpClient(_httpClient); + var httpClient = new SsdpHttpClient(_httpClient, _config); var document = await httpClient.GetDataAsync(new Uri(Properties.BaseUrl + url)); RendererCommands = TransportCommands.Create(document); @@ -641,13 +642,13 @@ namespace MediaBrowser.Dlna.PlayTo set; } - public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger) + public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger) { - var ssdpHttpClient = new SsdpHttpClient(httpClient); + var ssdpHttpClient = new SsdpHttpClient(httpClient, config); var document = await ssdpHttpClient.GetDataAsync(url).ConfigureAwait(false); - var deviceProperties = new DeviceProperties(); + var deviceProperties = new DeviceInfo(); var name = document.Descendants(uPnpNamespaces.ud.GetName("friendlyName")).FirstOrDefault(); if (name != null) @@ -705,7 +706,7 @@ namespace MediaBrowser.Dlna.PlayTo foreach (var element in servicesList) { - var service = uService.Create(element); + var service = Create(element); if (service != null) { @@ -721,7 +722,7 @@ namespace MediaBrowser.Dlna.PlayTo if (isRenderer) { - var device = new Device(deviceProperties, httpClient, logger); + var device = new Device(deviceProperties, httpClient, logger, config); await device.GetRenderingProtocolAsync().ConfigureAwait(false); await device.GetAVProtocolAsync().ConfigureAwait(false); @@ -734,6 +735,17 @@ namespace MediaBrowser.Dlna.PlayTo #endregion + private static DeviceService Create(XElement element) + { + var type = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceType")); + var id = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceId")); + var scpdUrl = element.GetDescendantValue(uPnpNamespaces.ud.GetName("SCPDURL")); + var controlURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("controlURL")); + var eventSubURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("eventSubURL")); + + return new DeviceService(type, id, scpdUrl, controlURL, eventSubURL); + } + #region Events public event EventHandler<TransportStateEventArgs> PlaybackChanged; @@ -788,4 +800,3 @@ namespace MediaBrowser.Dlna.PlayTo } } - diff --git a/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs new file mode 100644 index 000000000..f952b725e --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class DeviceInfo + { + public DeviceInfo() + { + ClientType = "DLNA"; + Name = "Generic Device"; + } + + public string UUID { get; set; } + + public string Name { 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 ModelNumber { get; set; } + + public string Manufacturer { get; set; } + + public string ManufacturerUrl { get; set; } + + public string PresentationUrl { get; set; } + + private string _baseUrl = string.Empty; + public string BaseUrl + { + get + { + return _baseUrl; + } + set + { + _baseUrl = value; + } + } + + public uIcon Icon { get; set; } + + private readonly List<DeviceService> _services = new List<DeviceService>(); + public List<DeviceService> Services + { + get + { + return _services; + } + } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/DeviceProperties.cs b/MediaBrowser.Dlna/PlayTo/DeviceProperties.cs deleted file mode 100644 index 395689575..000000000 --- a/MediaBrowser.Dlna/PlayTo/DeviceProperties.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Dlna.PlayTo -{ - public class DeviceProperties - { - private string _uuid = string.Empty; - public string UUID - { - get - { - return _uuid; - } - set - { - _uuid = value; - } - } - - private string _name = "PlayTo 1.0.0.0"; - public string Name - { - get - { - return _name; - } - set - { - _name = value; - } - } - - private string _clientType = "DLNA"; - public string ClientType - { - get - { - return _clientType; - } - set - { - _clientType = value; - } - } - - private string _displayName = string.Empty; - public string DisplayName - { - get - { - return string.IsNullOrEmpty(_displayName) ? _name : _displayName; - } - set - { - _displayName = value; - } - } - - private string _modelName = string.Empty; - public string ModelName - { - get - { - return _modelName; - } - set - { - _modelName = value; - } - } - - private string _modelNumber = string.Empty; - public string ModelNumber - { - get - { - return _modelNumber; - } - set - { - _modelNumber = value; - } - } - - private string _manufacturer = string.Empty; - public string Manufacturer - { - get - { - return _manufacturer; - } - set - { - _manufacturer = value; - } - } - - private string _manufacturerUrl = string.Empty; - public string ManufacturerUrl - { - get - { - return _manufacturerUrl; - } - set - { - _manufacturerUrl = value; - } - } - - private string _presentationUrl = string.Empty; - public string PresentationUrl - { - get - { - return _presentationUrl; - } - set - { - _presentationUrl = value; - } - } - - private string _baseUrl = string.Empty; - public string BaseUrl - { - get - { - return _baseUrl; - } - set - { - _baseUrl = value; - } - } - - private uIcon _icon; - public uIcon Icon - { - get - { - return _icon; - } - set - { - _icon = value; - } - } - - private string _iconUrl; - public string IconUrl - { - get - { - if (string.IsNullOrWhiteSpace(_iconUrl) && _icon != null) - { - if (!_icon.Url.StartsWith("/")) - _iconUrl = _baseUrl + "/" + _icon.Url; - else - _iconUrl = _baseUrl + _icon.Url; - } - - return _iconUrl; - } - } - - private readonly List<uService> _services = new List<uService>(); - public List<uService> Services - { - get - { - return _services; - } - } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/DeviceService.cs b/MediaBrowser.Dlna/PlayTo/DeviceService.cs new file mode 100644 index 000000000..082128b22 --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/DeviceService.cs @@ -0,0 +1,30 @@ + +namespace MediaBrowser.Dlna.PlayTo +{ + public class DeviceService + { + public string ServiceType { get; set; } + + public string ServiceId { get; set; } + + public string ScpdUrl { get; set; } + + public string ControlUrl { get; set; } + + public string EventSubUrl { get; set; } + + public DeviceService(string serviceType, string serviceId, string scpdUrl, string controlUrl, string eventSubUrl) + { + ServiceType = serviceType; + ServiceId = serviceId; + ScpdUrl = scpdUrl; + ControlUrl = controlUrl; + EventSubUrl = eventSubUrl; + } + + public override string ToString() + { + return string.Format("{0}", ServiceId); + } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs index 2be82b985..5836a1639 100644 --- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs +++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs @@ -1,9 +1,9 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; -using MediaBrowser.Dlna.PlayTo.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; @@ -21,13 +21,13 @@ namespace MediaBrowser.Dlna.PlayTo { private Device _device; private BaseItem _currentItem = null; - private TranscodeSettings[] _transcodeSettings; private readonly SessionInfo _session; private readonly ISessionManager _sessionManager; private readonly IItemRepository _itemRepository; private readonly ILibraryManager _libraryManager; private readonly INetworkManager _networkManager; private readonly ILogger _logger; + private readonly IDlnaManager _dlnaManager; private bool _playbackStarted = false; public bool SupportsMediaRemoteControl @@ -46,19 +46,19 @@ namespace MediaBrowser.Dlna.PlayTo } } - public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, INetworkManager networkManager) + public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, INetworkManager networkManager, IDlnaManager dlnaManager) { _session = session; _itemRepository = itemRepository; _sessionManager = sessionManager; _libraryManager = libraryManager; _networkManager = networkManager; + _dlnaManager = dlnaManager; _logger = logger; } - public void Init(Device device, TranscodeSettings[] transcodeSettings) + public void Init(Device device) { - _transcodeSettings = transcodeSettings; _device = device; _device.PlaybackChanged += Device_PlaybackChanged; _device.CurrentIdChanged += Device_CurrentIdChanged; @@ -384,7 +384,9 @@ namespace MediaBrowser.Dlna.PlayTo { var streams = _itemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = item.Id }).ToList(); - var playlistItem = PlaylistItem.GetBasicConfig(item, _transcodeSettings); + var deviceInfo = _device.Properties; + + var playlistItem = PlaylistItem.Create(item, _dlnaManager.GetProfile(deviceInfo.Name, deviceInfo.ModelName, deviceInfo.ModelNumber)); playlistItem.StartPositionTicks = startPostionTicks; if (playlistItem.IsAudio) @@ -444,6 +446,7 @@ namespace MediaBrowser.Dlna.PlayTo return true; } nextTrack.PlayState = 1; + _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, nextTrack.DlnaHeaders); await _device.SetAvTransport(nextTrack.StreamUrl, nextTrack.DlnaHeaders, nextTrack.Didl); if (nextTrack.StartPositionTicks > 0 && !nextTrack.Transcode) await _device.Seek(TimeSpan.FromTicks(nextTrack.StartPositionTicks)); @@ -487,4 +490,3 @@ namespace MediaBrowser.Dlna.PlayTo } } } - diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 59827b810..d1fdc9626 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -1,9 +1,9 @@ using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; -using MediaBrowser.Dlna.PlayTo.Configuration; using MediaBrowser.Model.Logging; using System; using System.Collections.Concurrent; @@ -29,9 +29,11 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IItemRepository _itemRepository; private readonly ILibraryManager _libraryManager; private readonly INetworkManager _networkManager; - private readonly IUserManager _userManager; + private readonly IUserManager _userManager; + private readonly IDlnaManager _dlnaManager; + private readonly IServerConfigurationManager _config; - public PlayToManager(ILogger logger, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepository, ILibraryManager libraryManager, INetworkManager networkManager, IUserManager userManager) + public PlayToManager(ILogger logger, IServerConfigurationManager config, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepository, ILibraryManager libraryManager, INetworkManager networkManager, IUserManager userManager, IDlnaManager dlnaManager) { _locations = new ConcurrentDictionary<string, DateTime>(); _tokenSource = new CancellationTokenSource(); @@ -43,6 +45,8 @@ namespace MediaBrowser.Dlna.PlayTo _libraryManager = libraryManager; _networkManager = networkManager; _userManager = userManager; + _dlnaManager = dlnaManager; + _config = config; } public async void Start() @@ -210,11 +214,11 @@ namespace MediaBrowser.Dlna.PlayTo if (!IsUriValid(uri)) return; - var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger).ConfigureAwait(false); + var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false); if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive)) { - var transcodeProfiles = TranscodeSettings.GetProfileSettings(device.Properties); + GetProfileSettings(device.Properties); var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, device.Properties.Name, device.Properties.UUID, device.Properties.DisplayName, uri.OriginalString, null) .ConfigureAwait(false); @@ -223,30 +227,33 @@ namespace MediaBrowser.Dlna.PlayTo if (controller == null) { - sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager); + sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager, _dlnaManager); } - controller.Init(device, transcodeProfiles); - + controller.Init(device); + _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); } } - const string DefaultUser = "Play To"; - private async Task<User> GetPlayToUser() + /// <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 user = _userManager.Users.FirstOrDefault(u => string.Equals(DefaultUser, u.Name, StringComparison.OrdinalIgnoreCase)); + var profile = _dlnaManager.GetProfile(deviceProperties.DisplayName, deviceProperties.ModelName, + deviceProperties.ModelNumber); - if (user == null) + if (!string.IsNullOrWhiteSpace(profile.Name)) { - user = await _userManager.CreateUser(DefaultUser); - - user.Configuration.IsHidden = true; - user.Configuration.IsAdministrator = false; - user.SaveConfiguration(); + deviceProperties.DisplayName = profile.Name; + } + if (!string.IsNullOrWhiteSpace(profile.ClientType)) + { + deviceProperties.ClientType = profile.ClientType; } - - return user; } /// <summary> diff --git a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs index a6746cfc5..a7afeab3c 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Plugins; @@ -11,7 +12,7 @@ namespace MediaBrowser.Dlna.PlayTo { public class PlayToServerEntryPoint : IServerEntryPoint { - private PlayToManager _manager; + private PlayToManager _manager; private readonly IServerConfigurationManager _config; private readonly ILogger _logger; private readonly ISessionManager _sessionManager; @@ -20,8 +21,9 @@ namespace MediaBrowser.Dlna.PlayTo private readonly ILibraryManager _libraryManager; private readonly INetworkManager _networkManager; private readonly IUserManager _userManager; + private readonly IDlnaManager _dlnaManager; - public PlayToServerEntryPoint(ILogManager logManager, IServerConfigurationManager config, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, INetworkManager networkManager, IUserManager userManager) + public PlayToServerEntryPoint(ILogManager logManager, IServerConfigurationManager config, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, INetworkManager networkManager, IUserManager userManager, IDlnaManager dlnaManager) { _config = config; _sessionManager = sessionManager; @@ -30,12 +32,14 @@ namespace MediaBrowser.Dlna.PlayTo _libraryManager = libraryManager; _networkManager = networkManager; _userManager = userManager; + _dlnaManager = dlnaManager; _logger = logManager.GetLogger("PlayTo"); } public void Run() { _config.ConfigurationUpdated += ConfigurationUpdated; + ReloadPlayToManager(); } @@ -65,7 +69,7 @@ namespace MediaBrowser.Dlna.PlayTo { try { - _manager = new PlayToManager(_logger, _sessionManager, _httpClient, _itemRepo, _libraryManager, _networkManager, _userManager); + _manager = new PlayToManager(_logger, _config, _sessionManager, _httpClient, _itemRepo, _libraryManager, _networkManager, _userManager, _dlnaManager); _manager.Start(); } catch (Exception ex) @@ -95,13 +99,9 @@ namespace MediaBrowser.Dlna.PlayTo } } - #region Dispose - public void Dispose() { DisposePlayToManager(); } - - #endregion } } diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs index 6523eb9f5..cfb2c7d1c 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs @@ -1,6 +1,9 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Dlna.PlayTo.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; using System; +using System.IO; +using System.Linq; namespace MediaBrowser.Dlna.PlayTo { @@ -28,84 +31,71 @@ namespace MediaBrowser.Dlna.PlayTo public long StartPositionTicks { get; set; } - public static PlaylistItem GetBasicConfig(BaseItem item, TranscodeSettings[] profileTranscodings) + public static PlaylistItem Create(BaseItem item, DlnaProfile profile) { + var playlistItem = new PlaylistItem + { + ItemId = item.Id.ToString() + }; - var playlistItem = new PlaylistItem(); - playlistItem.ItemId = item.Id.ToString(); - - if (string.Equals(item.MediaType, Model.Entities.MediaType.Video, StringComparison.OrdinalIgnoreCase)) + DlnaProfileType profileType; + if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) { playlistItem.IsVideo = true; + profileType = DlnaProfileType.Video; } else { playlistItem.IsAudio = true; + profileType = DlnaProfileType.Audio; } + var path = item.Path; - var path = item.Path.ToLower(); + var directPlay = profile.DirectPlayProfiles.FirstOrDefault(i => i.Type == profileType && IsSupported(i, path)); - //Check the DlnaProfile associated with the renderer - if (profileTranscodings != null) + if (directPlay != null) { - foreach (TranscodeSettings transcodeSetting in profileTranscodings) - { - if (string.IsNullOrWhiteSpace(transcodeSetting.Container)) - continue; - if (path.EndsWith(transcodeSetting.Container) && !string.IsNullOrWhiteSpace(transcodeSetting.TargetContainer)) - { - playlistItem.Transcode = true; - playlistItem.FileFormat = transcodeSetting.TargetContainer; - - if (string.IsNullOrWhiteSpace(transcodeSetting.MimeType)) - playlistItem.MimeType = transcodeSetting.MimeType; - - return playlistItem; - } - if (path.EndsWith(transcodeSetting.Container) && !string.IsNullOrWhiteSpace(transcodeSetting.MimeType)) - { - playlistItem.Transcode = false; - playlistItem.FileFormat = transcodeSetting.Container; - playlistItem.MimeType = transcodeSetting.MimeType; - return playlistItem; - } - } + playlistItem.Transcode = false; + playlistItem.FileFormat = Path.GetExtension(path); + playlistItem.MimeType = directPlay.MimeType; + return playlistItem; } - if (playlistItem.IsVideo) - { - //Check to see if we support serving the format statically - foreach (string supported in PlayToConfiguration.SupportedStaticFormats) - { - if (path.EndsWith(supported)) - { - playlistItem.Transcode = false; - playlistItem.FileFormat = supported; - return playlistItem; - } - } + var transcodingProfile = profile.TranscodingProfiles.FirstOrDefault(i => i.Type == profileType && IsSupported(profile, i, path)); - playlistItem.Transcode = true; - playlistItem.FileFormat = "ts"; - } - else + if (transcodingProfile != null) { - foreach (string supported in PlayToConfiguration.SupportedStaticFormats) - { - if (path.EndsWith(supported)) - { - playlistItem.Transcode = false; - playlistItem.FileFormat = supported; - return playlistItem; - } - } - playlistItem.Transcode = true; - playlistItem.FileFormat = "mp3"; + //Just to make sure we have a "." for the url, remove it in case a user adds it or not + playlistItem.FileFormat = "." + transcodingProfile.Container.TrimStart('.'); + + playlistItem.MimeType = transcodingProfile.MimeType; } return playlistItem; } + + private static bool IsSupported(DirectPlayProfile profile, string path) + { + var mediaContainer = Path.GetExtension(path); + + if (!profile.Containers.Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase))) + { + return false; + } + + // Placeholder for future conditions + + // TODO: Support codec list as additional restriction + + return true; + } + + private static bool IsSupported(DlnaProfile profile, TranscodingProfile transcodingProfile, string path) + { + // Placeholder for future conditions + return true; + } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs index 7179ef762..7a4928e5c 100644 --- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs +++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; using System; using System.IO; using System.Net; @@ -16,15 +17,17 @@ namespace MediaBrowser.Dlna.PlayTo private static readonly CookieContainer Container = new CookieContainer(); private readonly IHttpClient _httpClient; + private readonly IServerConfigurationManager _config; - public SsdpHttpClient(IHttpClient httpClient) + public SsdpHttpClient(IHttpClient httpClient, IServerConfigurationManager config) { _httpClient = httpClient; + _config = config; } - public async Task<XDocument> SendCommandAsync(string baseUrl, uService 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("/")) serviceUrl = "/" + serviceUrl; @@ -45,7 +48,8 @@ namespace MediaBrowser.Dlna.PlayTo var options = new HttpRequestOptions { Url = url.ToString(), - UserAgent = USERAGENT + UserAgent = USERAGENT, + LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging }; options.RequestHeaders["HOST"] = ip + ":" + port; @@ -83,7 +87,8 @@ namespace MediaBrowser.Dlna.PlayTo var options = new HttpRequestOptions { Url = url.ToString(), - UserAgent = USERAGENT + UserAgent = USERAGENT, + LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging }; options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; @@ -106,7 +111,8 @@ namespace MediaBrowser.Dlna.PlayTo var options = new HttpRequestOptions { Url = url.ToString(), - UserAgent = USERAGENT + UserAgent = USERAGENT, + LogRequest = _config.Configuration.DlnaOptions.EnablePlayToDebugLogging }; options.RequestHeaders["SOAPAction"] = soapAction; diff --git a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs index 3492ed182..ea95ea8e6 100644 --- a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs +++ b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Dlna.PlayTo internal static string GetAudioUrl(PlaylistItem item, string serverAddress) { if (!item.Transcode) - return string.Format("{0}/audio/{1}/stream.{2}?Static=True", serverAddress, item.ItemId, item.FileFormat); + return string.Format("{0}/audio/{1}/stream{2}?Static=True", serverAddress, item.ItemId, item.FileFormat); return string.Format("{0}/audio/{1}/stream.mp3?AudioCodec=Mp3", serverAddress, item.ItemId); } @@ -94,13 +94,13 @@ namespace MediaBrowser.Dlna.PlayTo /// <param name="streams">The streams.</param> /// <param name="serverAddress">The server address.</param> /// <returns>The url to send to the device</returns> - internal static string GetVideoUrl(DeviceProperties deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress) + internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress) { string dlnaCommand = string.Empty; if (!item.Transcode) { dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, null, null, null, null, null, null, null, null, null, null, item.MimeType); - return string.Format("{0}/Videos/{1}/stream.{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand); + return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand); } var videostream = streams.Where(m => m.Type == MediaStreamType.Video).OrderBy(m => m.IsDefault).FirstOrDefault(); var audiostream = streams.Where(m => m.Type == MediaStreamType.Audio).OrderBy(m => m.IsDefault).FirstOrDefault(); @@ -121,7 +121,7 @@ namespace MediaBrowser.Dlna.PlayTo } dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, videoCodec, audioCodec, null, null, videoBitrate, audioChannels, audioBitrate, item.StartPositionTicks, "baseline", "3", item.MimeType); - return string.Format("{0}/Videos/{1}/stream.{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand); + return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand); } /// <summary> @@ -189,4 +189,4 @@ namespace MediaBrowser.Dlna.PlayTo #endregion } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/uService.cs b/MediaBrowser.Dlna/PlayTo/uService.cs deleted file mode 100644 index 08bdf18fc..000000000 --- a/MediaBrowser.Dlna/PlayTo/uService.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Xml.Linq; - -namespace MediaBrowser.Dlna.PlayTo -{ - public class uService - { - public string ServiceType { get; set; } - - public string ServiceId { get; set; } - - public string SCPDURL { get; set; } - - public string ControlURL { get; set; } - - public string EventSubURL { get; set; } - - public uService(string serviceType, string serviceId, string scpdUrl, string controlUrl, string eventSubUrl) - { - ServiceType = serviceType; - ServiceId = serviceId; - SCPDURL = scpdUrl; - ControlURL = controlUrl; - EventSubURL = eventSubUrl; - } - - public static uService Create(XElement element) - { - var type = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceType")); - var id = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceId")); - var scpdUrl = element.GetDescendantValue(uPnpNamespaces.ud.GetName("SCPDURL")); - var controlURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("controlURL")); - var eventSubURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("eventSubURL")); - - return new uService(type, id, scpdUrl, controlURL, eventSubURL); - } - - public override string ToString() - { - return string.Format("{0}", ServiceId); - } - } -} diff --git a/MediaBrowser.Model/Configuration/DlnaOptions.cs b/MediaBrowser.Model/Configuration/DlnaOptions.cs index e6c24fdfb..67145e664 100644 --- a/MediaBrowser.Model/Configuration/DlnaOptions.cs +++ b/MediaBrowser.Model/Configuration/DlnaOptions.cs @@ -4,5 +4,6 @@ namespace MediaBrowser.Model.Configuration public class DlnaOptions { public bool EnablePlayTo { get; set; } + public bool EnablePlayToDebugLogging { get; set; } } } diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 3df25425d..2145860c7 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -57,8 +57,6 @@ namespace MediaBrowser.Model.Configuration public UnratedItem[] BlockUnratedItems { get; set; } - public bool DisplayMovieFormatRibbons { get; set; } - /// <summary> /// Initializes a new instance of the <see cref="UserConfiguration" /> class. /// </summary> diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 43ee7bdbc..e36d8a320 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -7,6 +7,7 @@ using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Text; using System.Threading; @@ -31,9 +32,86 @@ namespace MediaBrowser.Providers.Music public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) { + var releaseId = searchInfo.GetReleaseId(); + + string url = null; + + if (!string.IsNullOrEmpty(releaseId)) + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=reid:{0}", releaseId); + } + else + { + var artistMusicBrainzId = searchInfo.GetMusicBrainzArtistId(); + + if (!string.IsNullOrWhiteSpace(artistMusicBrainzId)) + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", + WebUtility.UrlEncode(searchInfo.Name), + artistMusicBrainzId); + } + else + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", + WebUtility.UrlEncode(searchInfo.Name), + WebUtility.UrlEncode(searchInfo.GetAlbumArtist())); + } + } + + if (!string.IsNullOrWhiteSpace(url)) + { + var doc = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + + return GetResultsFromResponse(doc); + } + return new List<RemoteSearchResult>(); } + private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc) + { + var ns = new XmlNamespaceManager(doc.NameTable); + ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + + var list = new List<RemoteSearchResult>(); + + var nodes = doc.SelectNodes("//mb:release-list/mb:release", ns); + + if (nodes != null) + { + foreach (var node in nodes.Cast<XmlNode>()) + { + if (node.Attributes != null) + { + string name = null; + + string mbzId = node.Attributes["id"].Value; + + var nameNode = node.SelectSingleNode("//mb:title", ns); + + if (nameNode != null) + { + name = nameNode.InnerText; + } + + if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name)) + { + var result = new RemoteSearchResult + { + Name = name + }; + + result.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbzId); + + list.Add(result); + } + } + } + } + + return list; + } + public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken) { var releaseId = id.GetReleaseId(); @@ -146,7 +224,7 @@ namespace MediaBrowser.Providers.Music { result.ReleaseGroupId = releaseGroupIdNode.Value; } - + return result; } diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 7c0233d3e..12a1bdd35 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -19,70 +19,120 @@ namespace MediaBrowser.Providers.Music { public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); - } - - public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) - { - var result = new MetadataResult<MusicArtist>(); - - var musicBrainzId = id.GetMusicBrainzArtistId() ?? await FindId(id, cancellationToken).ConfigureAwait(false); + var musicBrainzId = searchInfo.GetMusicBrainzArtistId(); if (!string.IsNullOrWhiteSpace(musicBrainzId)) { - cancellationToken.ThrowIfCancellationRequested(); + var url = string.Format("http://www.musicbrainz.org/ws/2/artist/?query=arid:{0}", musicBrainzId); - result.Item = new MusicArtist(); - result.HasMetadata = true; + var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken) + .ConfigureAwait(false); - result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId); + return GetResultsFromResponse(doc); } + else + { + // They seem to throw bad request failures on any term with a slash + var nameToSearch = searchInfo.Name.Replace('/', ' '); - return result; - } - - /// <summary> - /// Finds the id from music brainz. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{System.String}.</returns> - private async Task<string> FindId(ItemLookupInfo item, CancellationToken cancellationToken) - { - // They seem to throw bad request failures on any term with a slash - var nameToSearch = item.Name.Replace('/', ' '); + var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); + + var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + + var results = GetResultsFromResponse(doc).ToList(); + + if (results.Count > 0) + { + return results; + } - var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); + if (HasDiacritics(searchInfo.Name)) + { + // Try again using the search with accent characters url + url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + + doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + + return GetResultsFromResponse(doc); + } + } - var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + return new List<RemoteSearchResult>(); + } + private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc) + { var ns = new XmlNamespaceManager(doc.NameTable); ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); - var node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns); - if (node != null && node.Value != null) + var list = new List<RemoteSearchResult>(); + + var nodes = doc.SelectNodes("//mb:artist-list/mb:artist", ns); + + if (nodes != null) { - return node.Value; + foreach (var node in nodes.Cast<XmlNode>()) + { + if (node.Attributes != null) + { + string name = null; + + string mbzId = node.Attributes["id"].Value; + + var nameNode = node.SelectSingleNode("//mb:name", ns); + + if (nameNode != null) + { + name = nameNode.InnerText; + } + + if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name)) + { + var result = new RemoteSearchResult + { + Name = name + }; + + result.SetProviderId(MetadataProviders.MusicBrainzArtist, mbzId); + + list.Add(result); + } + } + } } - if (HasDiacritics(item.Name)) + return list; + } + + public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) + { + var result = new MetadataResult<MusicArtist> { - // Try again using the search with accent characters url - url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + Item = new MusicArtist() + }; - doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + var musicBrainzId = id.GetMusicBrainzArtistId(); - ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); - node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns); + if (string.IsNullOrWhiteSpace(musicBrainzId)) + { + var searchResults = await GetSearchResults(id, cancellationToken).ConfigureAwait(false); + + var singleResult = searchResults.FirstOrDefault(); - if (node != null && node.Value != null) + if (singleResult != null) { - return node.Value; + musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); + result.Item.Name = singleResult.Name; } } - return null; + if (!string.IsNullOrWhiteSpace(musicBrainzId)) + { + result.HasMetadata = true; + result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId); + } + + return result; } /// <summary> diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e9aebb6d2..32932fe0b 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -11,6 +11,7 @@ using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -29,6 +30,7 @@ using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Themes; +using MediaBrowser.Dlna; using MediaBrowser.Dlna.PlayTo; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; @@ -490,6 +492,9 @@ namespace MediaBrowser.ServerApplication var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger); RegisterSingleInstance<IAppThemeManager>(appThemeManager); + var dlnaManager = new DlnaManager(); + RegisterSingleInstance<IDlnaManager>(dlnaManager); + var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor); RegisterSingleInstance<ICollectionManager>(collectionManager); diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 3e548e625..9ffd2c3e2 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.339</version> + <version>3.0.340</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.339" /> + <dependency id="MediaBrowser.Common" version="3.0.340" /> <dependency id="NLog" version="2.1.0" /> <dependency id="SimpleInjector" version="2.4.1" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 5b81a046e..49d410c57 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.339</version> + <version>3.0.340</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index bf8bfd157..acbce81ae 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.339</version> + <version>3.0.340</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.339" /> + <dependency id="MediaBrowser.Common" version="3.0.340" /> </dependencies> </metadata> <files> |
