diff --git a/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs b/MediaBrowser.Controller/Dlna/DirectPlayProfile.cs new file mode 100644 index 0000000000..f1922dd323 --- /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 0000000000..33f95b7944 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/DlnaProfile.cs @@ -0,0 +1,54 @@ + +namespace MediaBrowser.Controller.Dlna +{ + public class DlnaProfile + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + /// + /// Gets or sets the type of the client. + /// + /// The type of the client. + public string ClientType { get; set; } + + /// + /// Gets or sets the name of the friendly. + /// + /// The name of the friendly. + public string FriendlyName { get; set; } + + /// + /// Gets or sets the model number. + /// + /// The model number. + public string ModelNumber { get; set; } + + /// + /// Gets or sets the name of the model. + /// + /// The name of the model. + public string ModelName { get; set; } + + /// + /// Gets or sets the transcoding profiles. + /// + /// The transcoding profiles. + public TranscodingProfile[] TranscodingProfiles { get; set; } + + /// + /// Gets or sets the direct play profiles. + /// + /// The direct play profiles. + public DirectPlayProfile[] DirectPlayProfiles { get; set; } + + public 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 0000000000..017dbc8746 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/IDlnaManager.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Dlna +{ + public interface IDlnaManager + { + /// + /// Gets the dlna profiles. + /// + /// IEnumerable{DlnaProfile}. + IEnumerable GetProfiles(); + + /// + /// Gets the default profile. + /// + /// DlnaProfile. + DlnaProfile GetDefaultProfile(); + + /// + /// Gets the profile. + /// + /// Name of the friendly. + /// Name of the model. + /// The model number. + /// DlnaProfile. + 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 0000000000..abc8868fb9 --- /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 23f8ac31a5..e0c792307e 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 images) + { + return AddImages(imageType, images.Cast()); + } + /// /// Adds the images. /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 16c54861ee..21a501b08e 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -73,6 +73,10 @@ + + + + diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs new file mode 100644 index 0000000000..a300026091 --- /dev/null +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -0,0 +1,202 @@ +using MediaBrowser.Controller.Dlna; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace MediaBrowser.Dlna +{ + public class DlnaManager : IDlnaManager + { + public IEnumerable GetProfiles() + { + var profile0 = new DlnaProfile + { + Name = "Samsung TV (B Series) [Profile]", + ClientType = "DLNA", + FriendlyName = "^TV$", + ModelNumber = @"1\.0", + ModelName = "Samsung DTV DMR", + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + } + } + }; + + 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)", + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + } + } + }; + + 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)", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + } + }, + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Containers = new[]{"mkv"}, + MimeType = "x-mkv", + Type = DlnaProfileType.Video + } + } + }; + + var profile3 = new DlnaProfile + { + Name = "Xbox 360 [Profile]", + ClientType = "DLNA", + ModelName = "Xbox 360", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + } + }; + + var profile4 = new DlnaProfile + { + Name = "Xbox One [Profile]", + ModelName = "Xbox One", + ClientType = "DLNA", + FriendlyName = "Xbox-SystemOS", + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video + } + } + }; + + var profile5 = new DlnaProfile + { + Name = "Sony Bravia TV (2012)", + ClientType = "TV", + FriendlyName = @"BRAVIA KDL-\d{2}[A-Z]X\d5(\d|G).*" + }; + + //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" + }; + + 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" + }; + + return new[] + { + profile0, + profile1, + profile2, + profile3, + profile4, + profile5, + profile6, + profile7 + }; + } + + public DlnaProfile GetDefaultProfile() + { + return new DlnaProfile(); + } + + 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(); + } + } +} diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 622ccefbc6..75879b3da2 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -51,15 +51,14 @@ Properties\SharedVersion.cs + - - - Code - + + @@ -81,7 +80,6 @@ - diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs b/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs deleted file mode 100644 index 70bda72387..0000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/DlnaProfile.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class DlnaProfile - { - /// - /// Gets or sets the name to be displayed. - /// - /// - /// The name. - /// - public string Name { get; set; } - - /// - /// Gets or sets the type of the client. - /// - /// - /// The type of the client. - /// - public string ClientType { get; set; } - - /// - /// Gets or sets the name of the friendly. - /// - /// - /// The name of the friendly. - /// - public string FriendlyName { get; set; } - - /// - /// Gets or sets the model number. - /// - /// - /// The model number. - /// - public string ModelNumber { get; set; } - - /// - /// Gets or sets the name of the model. - /// - /// - /// The name of the model. - /// - public string ModelName { get; set; } - - /// - /// Gets or sets the transcode settings. - /// - /// - /// The transcode settings. - /// - public TranscodeSetting[] TranscodeSettings { get; set; } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs b/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs deleted file mode 100644 index 927d8805b4..0000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/PlayToConfiguration.cs +++ /dev/null @@ -1,198 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Xml.Serialization; -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class PlayToConfiguration - { - [XmlIgnore] - public static PlayToConfiguration Instance - { - get; - private set; - } - - private static readonly string[] _supportedStaticFormats = { "mp3", "flac", "m4a", "wma", "avi", "mp4", "mkv", "ts" }; - - [XmlIgnore] - public string[] SupportedStaticFormats - { - get - { - return _supportedStaticFormats; - } - } - - public DlnaProfile[] Profiles - { get; set; } - - public 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 TranscodeSetting {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSetting {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSetting {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 TranscodeSetting {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSetting {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSetting {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 TranscodeSetting {Container = "mkv", MimeType = "x-mkv"}, - new TranscodeSetting {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSetting {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile3 = new DlnaProfile - { - Name = "Xbox 360 [Profile]", - ClientType = "DLNA", - ModelName = "Xbox 360", - TranscodeSettings = new[] - { - new TranscodeSetting {Container = "mkv", TargetContainer = "ts"}, - new TranscodeSetting {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSetting {Container = "m4a", TargetContainer = "mp3"} - } - }; - - var profile4 = new DlnaProfile - { - Name = "Xbox One [Profile]", - ModelName = "Xbox One", - ClientType = "DLNA", - FriendlyName = "Xbox-SystemOS", - TranscodeSettings = new[] - { - new TranscodeSetting {Container = "mkv", TargetContainer = "ts"}, - new TranscodeSetting {Container = "flac", TargetContainer = "mp3"}, - new TranscodeSetting {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 = TranscodeSetting.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 TranscodeSetting[] { } - }; - - 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 TranscodeSetting[] { } - }; - - return new[] - { - profile0, - profile1, - profile2, - profile3, - profile4, - profile5, - profile6, - profile7 - }; - } - - public static void Load(string path, ILogger logger) - { - if (!File.Exists(path)) - { - Instance = CreateNewSettingsFile(path, logger); - - } - else - { - try - { - XmlSerializer deserializer = new XmlSerializer(typeof(PlayToConfiguration)); - using (var textReader = new StreamReader(path)) - { - var configuration = (PlayToConfiguration)deserializer.Deserialize(textReader); - Instance = configuration; - textReader.Close(); - } - } - catch (Exception e) - { - // Something went wrong with the loading of the file - // Maybe a user created a faulty config? - // Delete the file and use default settings - logger.ErrorException("Error loading PlayTo configuration", e); - Instance = CreateNewSettingsFile(path, logger); - } - } - } - - private static PlayToConfiguration CreateNewSettingsFile(string path, ILogger logger) - { - var defaultConfig = new PlayToConfiguration(); - defaultConfig.Profiles = PlayToConfiguration.GetDefaultProfiles(); - - try - { - if (File.Exists(path)) - File.Delete(path); - - XmlSerializer serializer = new XmlSerializer(typeof(PlayToConfiguration)); - - using (var fileStream = new StreamWriter(path)) - { - serializer.Serialize(fileStream, defaultConfig); - fileStream.Close(); - } - } - catch(Exception e) - { - //Something went wrong deleting or creating the file, Log and continue with the default profile unsaved - logger.ErrorException("Error creating default PlayTo configuration", e); - } - return defaultConfig; - } - - } -} diff --git a/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs b/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs deleted file mode 100644 index 83ff92154f..0000000000 --- a/MediaBrowser.Dlna/PlayTo/Configuration/TranscodeSetting.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Text.RegularExpressions; - - -namespace MediaBrowser.Dlna.PlayTo.Configuration -{ - public class TranscodeSetting - { - /// - /// Gets or sets the container. - /// - /// - /// The container. - /// - public string Container { get; set; } - - /// - /// Gets or sets the target container. - /// - /// - /// The target container. - /// - public string TargetContainer { get; set; } - - /// - /// Gets or sets the Mimetype to enforce - /// - /// - /// The MimeType. - /// - public string MimeType { get; set; } - - /// - /// The default transcoding settings - /// - private static readonly TranscodeSetting[] DefaultTranscodingSettings = - { - new TranscodeSetting { Container = "mkv", TargetContainer = "ts" }, - new TranscodeSetting { Container = "flac", TargetContainer = "mp3" }, - new TranscodeSetting { Container = "m4a", TargetContainer = "mp3" } - }; - - public static TranscodeSetting[] GetDefaultTranscodingSettings() - { - return DefaultTranscodingSettings; - } - - /// - /// Gets the profile settings. - /// - /// The device properties. - /// The TranscodeSettings for the device - public static TranscodeSetting[] GetProfileSettings(DeviceProperties deviceProperties) - { - foreach (var profile in PlayToConfiguration.Instance.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 690f7525bb..c1436fa3c3 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Dlna.PlayTo private Timer _timer; - public DeviceProperties Properties { get; set; } + public DeviceInfo Properties { get; set; } private int _muteVol; public bool IsMuted @@ -120,7 +120,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IHttpClient _httpClient; private readonly ILogger _logger; - public Device(DeviceProperties deviceProperties, IHttpClient httpClient, ILogger logger) + public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger) { Properties = deviceProperties; _httpClient = httpClient; @@ -599,7 +599,7 @@ 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("/")) @@ -617,7 +617,7 @@ 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("/")) @@ -647,7 +647,7 @@ namespace MediaBrowser.Dlna.PlayTo 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 +705,7 @@ namespace MediaBrowser.Dlna.PlayTo foreach (var element in servicesList) { - var service = uService.Create(element); + var service = Create(element); if (service != null) { @@ -734,6 +734,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 PlaybackChanged; diff --git a/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs new file mode 100644 index 0000000000..91e8cb0be8 --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/DeviceInfo.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class DeviceInfo + { + public string UUID { get; set; } + + public string Name { get; set; } + + public string ClientType { get; set; } + + public string DisplayName { get; set; } + + 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 _services = new List(); + public List Services + { + get + { + return _services; + } + } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/DeviceProperties.cs b/MediaBrowser.Dlna/PlayTo/DeviceProperties.cs deleted file mode 100644 index 395689575a..0000000000 --- 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 _services = new List(); - public List Services - { - get - { - return _services; - } - } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/DeviceService.cs b/MediaBrowser.Dlna/PlayTo/DeviceService.cs new file mode 100644 index 0000000000..082128b225 --- /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 8892a03f12..0c13d83bd4 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 TranscodeSetting[] _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 @@ -56,9 +56,8 @@ namespace MediaBrowser.Dlna.PlayTo _logger = logger; } - public void Init(Device device, TranscodeSetting[] transcodeSettings) + public void Init(Device device) { - _transcodeSettings = transcodeSettings; _device = device; _device.PlaybackChanged += Device_PlaybackChanged; _device.CurrentIdChanged += Device_CurrentIdChanged; @@ -384,7 +383,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) diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index dfbbb4f807..a82859d1eb 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -1,10 +1,10 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; +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.Logging; using System; using System.Collections.Concurrent; @@ -16,7 +16,6 @@ using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml.Serialization; namespace MediaBrowser.Dlna.PlayTo { @@ -33,8 +32,9 @@ namespace MediaBrowser.Dlna.PlayTo private readonly ILibraryManager _libraryManager; private readonly INetworkManager _networkManager; private readonly IUserManager _userManager; + private readonly IDlnaManager _dlnaManager; - public PlayToManager(ILogger logger,IServerConfigurationManager config, 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(); _tokenSource = new CancellationTokenSource(); @@ -46,10 +46,9 @@ namespace MediaBrowser.Dlna.PlayTo _libraryManager = libraryManager; _networkManager = networkManager; _userManager = userManager; + _dlnaManager = dlnaManager; var path = Path.Combine(config.CommonApplicationPaths.ConfigurationDirectoryPath, "DlnaProfiles.xml"); - - PlayToConfiguration.Load(path, logger); } public async void Start() @@ -221,7 +220,7 @@ namespace MediaBrowser.Dlna.PlayTo if (device != null && device.RendererCommands != null && !_sessionManager.Sessions.Any(s => string.Equals(s.DeviceId, device.Properties.UUID) && s.IsActive)) { - var transcodeProfiles = TranscodeSetting.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); @@ -233,27 +232,24 @@ namespace MediaBrowser.Dlna.PlayTo sessionInfo.SessionController = controller = new PlayToController(sessionInfo, _sessionManager, _itemRepository, _libraryManager, _logger, _networkManager); } - 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 GetPlayToUser() + /// + /// Gets the profile settings. + /// + /// The device properties. + /// The TranscodeSettings for the device + 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) - { - user = await _userManager.CreateUser(DefaultUser); - - user.Configuration.IsHidden = true; - user.Configuration.IsAdministrator = false; - user.SaveConfiguration(); - } - - return user; + deviceProperties.DisplayName = profile.Name; + deviceProperties.ClientType = profile.ClientType; } /// diff --git a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs index 5b326d202a..a7afeab3c5 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,6 +32,7 @@ namespace MediaBrowser.Dlna.PlayTo _libraryManager = libraryManager; _networkManager = networkManager; _userManager = userManager; + _dlnaManager = dlnaManager; _logger = logManager.GetLogger("PlayTo"); } @@ -66,7 +69,7 @@ namespace MediaBrowser.Dlna.PlayTo { try { - _manager = new PlayToManager(_logger, _config, _sessionManager, _httpClient, _itemRepo, _libraryManager, _networkManager, _userManager); + _manager = new PlayToManager(_logger, _config, _sessionManager, _httpClient, _itemRepo, _libraryManager, _networkManager, _userManager, _dlnaManager); _manager.Start(); } catch (Exception ex) @@ -96,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 99f56bfd7d..ab2456fc87 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,69 @@ namespace MediaBrowser.Dlna.PlayTo public long StartPositionTicks { get; set; } - public static PlaylistItem GetBasicConfig(BaseItem item, TranscodeSetting[] 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 (TranscodeSetting 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).TrimStart('.'); + return playlistItem; } - if (playlistItem.IsVideo) + + var transcodingProfile = profile.TranscodingProfiles.FirstOrDefault(i => i.Type == profileType && IsSupported(profile, i, path)); + + if (transcodingProfile != null) { - - //Check to see if we support serving the format statically - foreach (string supported in PlayToConfiguration.Instance.SupportedStaticFormats) - { - if (path.EndsWith(supported)) - { - playlistItem.Transcode = false; - playlistItem.FileFormat = supported; - return playlistItem; - } - } - playlistItem.Transcode = true; - playlistItem.FileFormat = "ts"; - } - else - { - foreach (string supported in PlayToConfiguration.Instance.SupportedStaticFormats) - { - if (path.EndsWith(supported)) - { - playlistItem.Transcode = false; - playlistItem.FileFormat = supported; - return playlistItem; - } - } + playlistItem.FileFormat = transcodingProfile.Container; - playlistItem.Transcode = true; - playlistItem.FileFormat = "mp3"; + playlistItem.MimeType = transcodingProfile.MimeType; } return playlistItem; } + + private static bool IsSupported(DirectPlayProfile profile, string path) + { + // TODO: Support codec list as additional restriction + + var mediaContainer = Path.GetExtension(path).TrimStart('.'); + + if (!profile.Containers.Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase))) + { + return false; + } + + // Placeholder for future conditions + + return true; + } + + private static bool IsSupported(DlnaProfile profile, TranscodingProfile transcodingProfile, string path) + { + // Placeholder for future conditions + return true; + } } } diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs index 7179ef7622..bb03caf8e9 100644 --- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs +++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs @@ -22,9 +22,9 @@ namespace MediaBrowser.Dlna.PlayTo _httpClient = httpClient; } - public async Task SendCommandAsync(string baseUrl, uService service, string command, string postData, string header = null) + public async Task 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; diff --git a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs index 3492ed182e..a044ee7ec4 100644 --- a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs +++ b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Dlna.PlayTo /// The streams. /// The server address. /// The url to send to the device - internal static string GetVideoUrl(DeviceProperties deviceProperties, PlaylistItem item, List streams, string serverAddress) + internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List streams, string serverAddress) { string dlnaCommand = string.Empty; if (!item.Transcode) diff --git a/MediaBrowser.Dlna/PlayTo/uService.cs b/MediaBrowser.Dlna/PlayTo/uService.cs deleted file mode 100644 index 08bdf18fc8..0000000000 --- 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/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 3df25425d5..2145860c73 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; } - /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e9aebb6d20..32932fe0ba 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(appThemeManager); + var dlnaManager = new DlnaManager(); + RegisterSingleInstance(dlnaManager); + var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor); RegisterSingleInstance(collectionManager);