From 5ad04bbb7754eddaf07921ee0ec699a2a934c242 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 18 Oct 2016 01:06:48 -0400 Subject: [PATCH 1/7] update components --- .../Library/MediaSourceManager.cs | 1 - MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs | 1 - Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 716d627a9..e7bfe56f2 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -360,7 +360,6 @@ namespace MediaBrowser.Server.Implementations.Library public async Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) { - enableAutoClose = false; await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index aa404b37c..3577ba49b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2304,7 +2304,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); - info.RecordAnyChannel = true; info.RecordAnyTime = true; info.Days = new List { diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 31d946691..176de7305 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.663 + 3.0.664 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption. Copyright © Emby 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 86524c2b6..420842418 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.663 + 3.0.664 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 860a19436..f9f5c2956 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.663 + 3.0.664 Media Browser.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + From 2f17d160bc2c90d0fd54b42098fb7a60bc3c8264 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 18 Oct 2016 14:23:41 -0400 Subject: [PATCH 2/7] limit number of people in dlna responses --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 13 ++++++++ MediaBrowser.Dlna/Didl/DidlBuilder.cs | 22 +++++++++++++- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 1 + MediaBrowser.Model/LiveTv/ProgramQuery.cs | 1 + .../Library/LibraryManager.cs | 6 +++- .../LiveTv/EmbyTV/EncodedRecorder.cs | 7 ++++- .../LiveTv/LiveTvManager.cs | 1 + .../LiveTv/TunerHosts/M3uParser.cs | 30 ++++++++++++++----- 8 files changed, 71 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 4217cd6ab..90767b135 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -19,6 +19,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Api.Playback.Progressive; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Server.Implementations.LiveTv.EmbyTV; namespace MediaBrowser.Api.LiveTv @@ -390,6 +391,7 @@ namespace MediaBrowser.Api.LiveTv public bool? EnableUserData { get; set; } public string SeriesTimerId { get; set; } + public string LibrarySeriesId { get; set; } /// /// Fields to return within the items, in addition to basic information @@ -990,6 +992,17 @@ namespace MediaBrowser.Api.LiveTv query.SeriesTimerId = request.SeriesTimerId; query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + if (!string.IsNullOrWhiteSpace(request.LibrarySeriesId)) + { + query.IsSeries = true; + + var series = _libraryManager.GetItemById(request.LibrarySeriesId) as Series; + if (series != null) + { + query.Name = series.Name; + } + } + var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false); return ToOptimizedResult(result); diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 1330c54c2..a5091bf01 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -696,16 +696,36 @@ namespace MediaBrowser.Dlna.Didl private void AddPeople(BaseItem item, XmlElement element) { - var types = new[] { PersonType.Director, PersonType.Writer, PersonType.Producer, PersonType.Composer, "Creator" }; + var types = new[] + { + PersonType.Director, + PersonType.Writer, + PersonType.Producer, + PersonType.Composer, + "Creator" + }; var people = _libraryManager.GetPeople(item); + var index = 0; + + // Seeing some LG models locking up due content with large lists of people + // The actual issue might just be due to processing a more metadata than it can handle + var limit = 10; + foreach (var actor in people) { var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase)) ?? PersonType.Actor; AddValue(element, "upnp", type.ToLower(), actor.Name, NS_UPNP); + + index++; + + if (index >= limit) + { + break; + } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index ee7dd8b98..e19bddeee 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -16,6 +16,7 @@ namespace MediaBrowser.Model.LiveTv public string RecordingEncodingFormat { get; set; } public bool EnableRecordingSubfolders { get; set; } public bool EnableOriginalAudioWithEncodedRecordings { get; set; } + public bool EnableOriginalVideoWithEncodedRecordings { get; set; } public List TunerHosts { get; set; } public List ListingProviders { get; set; } diff --git a/MediaBrowser.Model/LiveTv/ProgramQuery.cs b/MediaBrowser.Model/LiveTv/ProgramQuery.cs index ad57d1473..1fd995760 100644 --- a/MediaBrowser.Model/LiveTv/ProgramQuery.cs +++ b/MediaBrowser.Model/LiveTv/ProgramQuery.cs @@ -42,6 +42,7 @@ namespace MediaBrowser.Model.LiveTv /// The user identifier. public string UserId { get; set; } public string SeriesTimerId { get; set; } + public string Name { get; set; } /// /// The earliest date for which a program starts to return diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index a45d7ae5f..64abcc044 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2840,7 +2840,11 @@ namespace MediaBrowser.Server.Implementations.Library { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { - return Directory.Exists(path); + // We can't validate protocol-based paths, so just allow them + if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) + { + return Directory.Exists(path); + } } // Without native support for unc, we cannot validate this when running under mono diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3e9d186e3..cdf8e7597 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var format = _liveTvOptions.RecordingEncodingFormat; - if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase) || _liveTvOptions.EnableOriginalVideoWithEncodedRecordings) { return "mkv"; } @@ -204,6 +204,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private bool EncodeVideo(MediaSourceInfo mediaSource) { + if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings) + { + return false; + } + var mediaStreams = mediaSource.MediaStreams ?? new List(); return !mediaStreams.Any(i => i.Type == MediaStreamType.Video && string.Equals(i.Codec, "h264", StringComparison.OrdinalIgnoreCase) && !i.IsInterlaced); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 3577ba49b..7c72363b0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -877,6 +877,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv SortOrder = query.SortOrder ?? SortOrder.Ascending, EnableTotalRecordCount = query.EnableTotalRecordCount, TopParentIds = new[] { topFolder.Id.ToString("N") }, + Name = query.Name, DtoOptions = options }; diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 38eb9bdd1..2bbd44952 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -111,15 +111,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts channel.Number = "0"; } - channel.ImageUrl = FindProperty("tvg-logo", extInf, null); - channel.Number = FindProperty("channel-id", extInf, channel.Number); - channel.Number = FindProperty("tvg-id", extInf, channel.Number); - channel.Name = FindProperty("tvg-id", extInf, channel.Name); - channel.Name = FindProperty("tvg-name", extInf, channel.Name); + channel.ImageUrl = FindProperty("tvg-logo", extInf); + + var name = FindProperty("tvg-name", extInf); + if (string.IsNullOrWhiteSpace(name)) + { + name = FindProperty("tvg-id", extInf); + } + + channel.Name = name; + + var numberString = FindProperty("tvg-id", extInf); + if (string.IsNullOrWhiteSpace(numberString)) + { + numberString = FindProperty("channel-id", extInf); + } + + if (!string.IsNullOrWhiteSpace(numberString)) + { + channel.Number = numberString; + } + return channel; } - private string FindProperty(string property, string properties, string defaultResult = "") + private string FindProperty(string property, string properties) { var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase); var matches = reg.Matches(properties); @@ -130,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts return match.Groups[2].Value; } } - return defaultResult; + return null; } } From d000cd4159f46eb1f0c26b5b8d3a3794bd7d9b1b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 18 Oct 2016 14:30:50 -0400 Subject: [PATCH 3/7] remote service restart --- MediaBrowser.ServerApplication/MainStartup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index d1972a938..b2c7445e2 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.ServerApplication if (_isRunningAsService) { - _canRestartService = CanRestartWindowsService(); + //_canRestartService = CanRestartWindowsService(); } var currentProcess = Process.GetCurrentProcess(); From d43111813eeb85db5e5c16520bfec53d9afdddc2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 18 Oct 2016 14:35:27 -0400 Subject: [PATCH 4/7] add user agent to m3u requests --- .../LiveTv/TunerHosts/M3UTunerHost.cs | 9 ++++++--- .../LiveTv/TunerHosts/M3uParser.cs | 13 +++++++++++-- .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 7 +++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index cedaf7ad8..48117f225 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Serialization; @@ -24,12 +25,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { private readonly IFileSystem _fileSystem; private readonly IHttpClient _httpClient; + private readonly IServerApplicationHost _appHost; - public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient) + public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) : base(config, logger, jsonSerializer, mediaEncoder) { _fileSystem = fileSystem; _httpClient = httpClient; + _appHost = appHost; } public override string Type @@ -46,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) { - return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); + return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); } public Task> GetTunerInfos(CancellationToken cancellationToken) @@ -75,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts public async Task Validate(TunerHostInfo info) { - using (var stream = await new M3uParser(Logger, _fileSystem, _httpClient).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) + using (var stream = await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) { } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 2bbd44952..454abdddd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Logging; @@ -18,12 +19,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IHttpClient _httpClient; + private readonly IServerApplicationHost _appHost; - public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient) + public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) { _logger = logger; _fileSystem = fileSystem; _httpClient = httpClient; + _appHost = appHost; } public async Task> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken) @@ -41,7 +44,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { - return _httpClient.Get(url, cancellationToken); + return _httpClient.Get(new HttpRequestOptions + { + Url = url, + CancellationToken = cancellationToken, + // Some data providers will require a user agent + UserAgent = _appHost.FriendlyName + "/" + _appHost.ApplicationVersion + }); } return Task.FromResult(_fileSystem.OpenRead(url)); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index 81deb2995..1fe767e52 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -8,6 +8,7 @@ using CommonIO; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; @@ -25,12 +26,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { private readonly IFileSystem _fileSystem; private readonly IHttpClient _httpClient; + private readonly IServerApplicationHost _appHost; - public SatIpHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient) + public SatIpHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) : base(config, logger, jsonSerializer, mediaEncoder) { _fileSystem = fileSystem; _httpClient = httpClient; + _appHost = appHost; } private const string ChannelIdPrefix = "sat_"; @@ -39,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { if (!string.IsNullOrWhiteSpace(tuner.M3UUrl)) { - return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); + return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); } var channels = await new ChannelScan(Logger).Scan(tuner, cancellationToken).ConfigureAwait(false); From f988413e4b3c67be7a03d99871043d6d078be725 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 19 Oct 2016 02:27:02 -0400 Subject: [PATCH 5/7] update ssdp handler --- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 73 +++++++++++++------ .../MediaBrowser.WebDashboard.csproj | 6 -- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index a8aedaed8..f1eeb0a0a 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -19,6 +19,7 @@ using System.Net; using System.Threading.Tasks; using MediaBrowser.Controller.MediaEncoding; using Rssdp; +using Rssdp.Infrastructure; namespace MediaBrowser.Dlna.Main { @@ -154,8 +155,14 @@ namespace MediaBrowser.Dlna.Main } } + private void LogMessage(string msg) + { + //_logger.Debug(msg); + } + private void StartPublishing() { + SsdpDevicePublisherBase.LogFunction = LogMessage; _Publisher = new SsdpDevicePublisher(); } @@ -237,46 +244,64 @@ namespace MediaBrowser.Dlna.Main var udn = (addressString).GetMD5().ToString("N"); - var services = new List + var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; + + _logger.Info("Registering publisher for {0} on {1}", fullService, addressString); + + var descriptorUri = "/dlna/" + udn + "/description.xml"; + var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri); + + var device = new SsdpRootDevice + { + CacheLifetime = TimeSpan.FromSeconds(cacheLength), //How long SSDP clients can cache this info. + Location = uri, // Must point to the URL that serves your devices UPnP description document. + FriendlyName = "Emby Server", + Manufacturer = "Emby", + ModelName = "Emby Server", + Uuid = udn + // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. + }; + + SetProperies(device, fullService); + _Publisher.AddDevice(device); + + var embeddedDevices = new List { - "urn:schemas-upnp-org:device:MediaServer:1", "urn:schemas-upnp-org:service:ContentDirectory:1", "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" }; - foreach (var fullService in services) + foreach (var subDevice in embeddedDevices) { - _logger.Info("Registering publisher for {0} on {1}", fullService, addressString); - - var descriptorURI = "/dlna/" + udn + "/description.xml"; - var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI); - - var service = fullService.Replace("urn:", string.Empty).Replace(":1", string.Empty); - - var serviceParts = service.Split(':'); - - var deviceTypeNamespace = serviceParts[0].Replace('.', '-'); - - var device = new SsdpRootDevice + var embeddedDevice = new SsdpEmbeddedDevice { - CacheLifetime = TimeSpan.FromSeconds(cacheLength), //How long SSDP clients can cache this info. - Location = uri, // Must point to the URL that serves your devices UPnP description document. - DeviceTypeNamespace = deviceTypeNamespace, - DeviceClass = serviceParts[1], - DeviceType = serviceParts[2], - FriendlyName = "Emby Server", - Manufacturer = "Emby", - ModelName = "Emby Server", + FriendlyName = device.FriendlyName, + Manufacturer = device.Manufacturer, + ModelName = device.ModelName, Uuid = udn // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. }; - _Publisher.AddDevice(device); + SetProperies(embeddedDevice, subDevice); + device.AddDevice(embeddedDevice); } } } + private void SetProperies(SsdpDevice device, string fullDeviceType) + { + var service = fullDeviceType.Replace("urn:", string.Empty).Replace(":1", string.Empty); + + var serviceParts = service.Split(':'); + + var deviceTypeNamespace = serviceParts[0].Replace('.', '-'); + + device.DeviceTypeNamespace = deviceTypeNamespace; + device.DeviceClass = serviceParts[1]; + device.DeviceType = serviceParts[2]; + } + private readonly object _syncLock = new object(); private void StartPlayToManager() { diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 36dd12651..a561a48af 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -986,9 +986,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -1034,9 +1031,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 7895b5457c5450864c3d8de4b0b35953420a4b5d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 19 Oct 2016 02:28:44 -0400 Subject: [PATCH 6/7] removed dead code --- MediaBrowser.Controller/Dlna/ISsdpHandler.cs | 8 - .../MediaBrowser.Controller.csproj | 1 - MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 4 - MediaBrowser.Dlna/Ssdp/Datagram.cs | 126 ------- MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs | 21 -- MediaBrowser.Dlna/Ssdp/Extensions.cs | 24 -- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 328 ------------------ MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs | 26 -- 8 files changed, 538 deletions(-) delete mode 100644 MediaBrowser.Controller/Dlna/ISsdpHandler.cs delete mode 100644 MediaBrowser.Dlna/Ssdp/Datagram.cs delete mode 100644 MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs delete mode 100644 MediaBrowser.Dlna/Ssdp/SsdpHandler.cs delete mode 100644 MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs diff --git a/MediaBrowser.Controller/Dlna/ISsdpHandler.cs b/MediaBrowser.Controller/Dlna/ISsdpHandler.cs deleted file mode 100644 index ec3a00aad..000000000 --- a/MediaBrowser.Controller/Dlna/ISsdpHandler.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace MediaBrowser.Controller.Dlna -{ - public interface ISsdpHandler - { - } -} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index a8062af19..36d59d3e4 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -111,7 +111,6 @@ - diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index ef60be227..ebffe6c57 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -108,7 +108,6 @@ - @@ -130,7 +129,6 @@ - @@ -160,8 +158,6 @@ - - diff --git a/MediaBrowser.Dlna/Ssdp/Datagram.cs b/MediaBrowser.Dlna/Ssdp/Datagram.cs deleted file mode 100644 index 590194534..000000000 --- a/MediaBrowser.Dlna/Ssdp/Datagram.cs +++ /dev/null @@ -1,126 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; - -namespace MediaBrowser.Dlna.Ssdp -{ - public class Datagram - { - public EndPoint ToEndPoint { get; private set; } - public EndPoint FromEndPoint { get; private set; } - public string Message { get; private set; } - public bool IsBroadcast { get; private set; } - public bool EnableDebugLogging { get; private set; } - - private readonly ILogger _logger; - - public Datagram(EndPoint toEndPoint, EndPoint fromEndPoint, ILogger logger, string message, bool isBroadcast, bool enableDebugLogging) - { - Message = message; - _logger = logger; - EnableDebugLogging = enableDebugLogging; - IsBroadcast = isBroadcast; - FromEndPoint = fromEndPoint; - ToEndPoint = toEndPoint; - } - - public void Send() - { - var msg = Encoding.ASCII.GetBytes(Message); - - var socket = CreateSocket(); - - if (socket == null) - { - return; - } - - if (FromEndPoint != null) - { - try - { - socket.Bind(FromEndPoint); - } - catch (Exception ex) - { - if (EnableDebugLogging) - { - _logger.ErrorException("Error binding datagram socket", ex); - } - - if (IsBroadcast) - { - CloseSocket(socket, false); - return; - } - } - } - - try - { - socket.BeginSendTo(msg, 0, msg.Length, SocketFlags.None, ToEndPoint, result => - { - try - { - socket.EndSend(result); - } - catch (Exception ex) - { - if (EnableDebugLogging) - { - _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString()); - } - } - finally - { - CloseSocket(socket, true); - } - }, null); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString()); - CloseSocket(socket, false); - } - } - - private void CloseSocket(Socket socket, bool logError) - { - try - { - socket.Close(); - } - catch (Exception ex) - { - if (logError && EnableDebugLogging) - { - _logger.ErrorException("Error closing datagram socket", ex); - } - } - } - - private Socket CreateSocket() - { - try - { - var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - - if (IsBroadcast) - { - socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); - } - - return socket; - } - catch (Exception ex) - { - _logger.ErrorException("Error creating socket", ex); - return null; - } - } - } -} diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs deleted file mode 100644 index e9de45522..000000000 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediaBrowser.Dlna.PlayTo; -using System; -using System.Net; - -namespace MediaBrowser.Dlna.Ssdp -{ - public class DeviceDiscoveryInfo - { - public Device Device { get; set; } - - /// - /// The server's ip address that the device responded to - /// - public IPAddress LocalIpAddress { get; set; } - - public Uri Uri { get; set; } - - public string Usn { get; set; } - public string Nt { get; set; } - } -} diff --git a/MediaBrowser.Dlna/Ssdp/Extensions.cs b/MediaBrowser.Dlna/Ssdp/Extensions.cs index 12589e80f..17ebcc7ea 100644 --- a/MediaBrowser.Dlna/Ssdp/Extensions.cs +++ b/MediaBrowser.Dlna/Ssdp/Extensions.cs @@ -9,30 +9,6 @@ namespace MediaBrowser.Dlna.Ssdp { public static class Extensions { - public static Task ReceiveAsync(this Socket socket, byte[] buffer, int offset, int size) - { - var tcs = new TaskCompletionSource(socket); - var remoteip = new IPEndPoint(IPAddress.Any, 0); - var endpoint = (EndPoint)remoteip; - - socket.BeginReceiveFrom(buffer, offset, size, SocketFlags.None, ref endpoint, iar => - { - var result = (TaskCompletionSource)iar.AsyncState; - var iarSocket = (Socket)result.Task.AsyncState; - - try - { - result.TrySetResult(iarSocket.EndReceive(iar)); - } - catch (Exception exc) - { - result.TrySetException(exc); - } - }, tcs); - - return tcs.Task; - } - public static string GetValue(this XElement container, XName name) { var node = container.Element(name); diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs deleted file mode 100644 index 0d0ca98a2..000000000 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ /dev/null @@ -1,328 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Dlna.Server; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Win32; - -namespace MediaBrowser.Dlna.Ssdp -{ - public class SsdpHandler : IDisposable, ISsdpHandler - { - private Socket _multicastSocket; - - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - - const string SSDPAddr = "239.255.255.250"; - const int SSDPPort = 1900; - private readonly string _serverSignature; - - private readonly IPAddress _ssdpIp = IPAddress.Parse(SSDPAddr); - private readonly IPEndPoint _ssdpEndp = new IPEndPoint(IPAddress.Parse(SSDPAddr), SSDPPort); - - private Timer _notificationTimer; - - private bool _isDisposed; - private readonly Dictionary> _devices = new Dictionary>(); - - private readonly IApplicationHost _appHost; - - private readonly int _unicastPort = 1901; - private UdpClient _unicastClient; - - public SsdpHandler(ILogger logger, IServerConfigurationManager config, IApplicationHost appHost) - { - _logger = logger; - _config = config; - _appHost = appHost; - - _config.NamedConfigurationUpdated += _config_ConfigurationUpdated; - _serverSignature = GenerateServerSignature(); - } - - private string GenerateServerSignature() - { - var os = Environment.OSVersion; - var pstring = os.Platform.ToString(); - switch (os.Platform) - { - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - pstring = "WIN"; - break; - } - - return String.Format( - "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 Emby/{4}", - pstring, - IntPtr.Size * 8, - os.Version.Major, - os.Version.Minor, - _appHost.ApplicationVersion - ); - } - - void _config_ConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) - { - if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) - { - ReloadAliveNotifier(); - } - } - - public IEnumerable RegisteredDevices - { - get - { - lock (_devices) - { - var devices = _devices.ToList(); - - return devices.SelectMany(i => i.Value).ToList(); - } - } - } - - public void Start() - { - DisposeSocket(); - StopAliveNotifier(); - - RestartSocketListener(); - ReloadAliveNotifier(); - - SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; - SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; - } - - void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) - { - if (e.Mode == PowerModes.Resume) - { - Start(); - } - } - - public async void SendDatagram(string msg, - EndPoint endpoint, - EndPoint localAddress, - bool isBroadcast, - int sendCount = 3) - { - var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLog; - - for (var i = 0; i < sendCount; i++) - { - if (i > 0) - { - await Task.Delay(500).ConfigureAwait(false); - } - - var dgram = new Datagram(endpoint, localAddress, _logger, msg, isBroadcast, enableDebugLogging); - dgram.Send(); - } - } - - private void RestartSocketListener() - { - if (_isDisposed) - { - return; - } - - try - { - _multicastSocket = CreateMulticastSocket(); - - _logger.Info("MultiCast socket created"); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating MultiCast socket", ex); - //StartSocketRetryTimer(); - } - } - - public void Dispose() - { - _config.NamedConfigurationUpdated -= _config_ConfigurationUpdated; - SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; - - _isDisposed = true; - - DisposeSocket(); - StopAliveNotifier(); - } - - private void DisposeSocket() - { - if (_multicastSocket != null) - { - _multicastSocket.Close(); - _multicastSocket.Dispose(); - _multicastSocket = null; - } - } - - private Socket CreateMulticastSocket() - { - var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); - socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_ssdpIp, 0)); - - socket.Bind(new IPEndPoint(IPAddress.Any, SSDPPort)); - - return socket; - } - - private void NotifyAll() - { - var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLog; - - if (enableDebugLogging) - { - _logger.Debug("Sending alive notifications"); - } - foreach (var d in RegisteredDevices) - { - NotifyDevice(d, "alive", enableDebugLogging); - } - } - - private void NotifyDevice(UpnpDevice dev, string type, bool logMessage) - { - const string header = "NOTIFY * HTTP/1.1"; - - var values = new Dictionary(StringComparer.OrdinalIgnoreCase); - - // If needed later for non-server devices, these headers will need to be dynamic - values["HOST"] = "239.255.255.250:1900"; - values["CACHE-CONTROL"] = "max-age = 600"; - values["LOCATION"] = dev.Descriptor.ToString(); - values["SERVER"] = _serverSignature; - values["NTS"] = "ssdp:" + type; - values["NT"] = dev.Type; - values["USN"] = dev.USN; - - if (logMessage) - { - _logger.Debug("{0} said {1}", dev.USN, type); - } - - var msg = new SsdpMessageBuilder().BuildMessage(header, values); - - SendDatagram(msg, _ssdpEndp, new IPEndPoint(dev.Address, 0), true, 2); - //SendUnicastRequest(msg, 1); - } - - public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable services) - { - lock (_devices) - { - List list; - List dl; - if (_devices.TryGetValue(uuid, out dl)) - { - list = dl; - } - else - { - list = new List(); - _devices[uuid] = list; - } - - list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); - - NotifyAll(); - _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); - } - } - - public void UnregisterNotification(string uuid) - { - lock (_devices) - { - List dl; - if (_devices.TryGetValue(uuid, out dl)) - { - _devices.Remove(uuid); - foreach (var d in dl.ToList()) - { - NotifyDevice(d, "byebye", true); - } - - _logger.Debug("Unregistered mount {0}", uuid); - } - } - } - - private readonly object _notificationTimerSyncLock = new object(); - private int _aliveNotifierIntervalMs; - private void ReloadAliveNotifier() - { - var config = _config.GetDlnaConfiguration(); - - if (!config.BlastAliveMessages) - { - StopAliveNotifier(); - return; - } - - var intervalMs = config.BlastAliveMessageIntervalSeconds * 1000; - - if (_notificationTimer == null || _aliveNotifierIntervalMs != intervalMs) - { - lock (_notificationTimerSyncLock) - { - if (_notificationTimer == null) - { - _logger.Debug("Starting alive notifier"); - const int initialDelayMs = 3000; - _notificationTimer = new Timer(state => NotifyAll(), null, initialDelayMs, intervalMs); - } - else - { - _logger.Debug("Updating alive notifier"); - _notificationTimer.Change(intervalMs, intervalMs); - } - - _aliveNotifierIntervalMs = intervalMs; - } - } - } - - private void StopAliveNotifier() - { - lock (_notificationTimerSyncLock) - { - if (_notificationTimer != null) - { - _logger.Debug("Stopping alive notifier"); - _notificationTimer.Dispose(); - _notificationTimer = null; - } - } - } - - public class UdpState - { - public UdpClient UdpClient; - public IPEndPoint EndPoint; - } - } -} diff --git a/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs b/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs deleted file mode 100644 index e479ca19a..000000000 --- a/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace MediaBrowser.Dlna.Ssdp -{ - public class SsdpMessageBuilder - { - public string BuildMessage(string header, Dictionary values) - { - var builder = new StringBuilder(); - - const string argFormat = "{0}: {1}\r\n"; - - builder.AppendFormat("{0}\r\n", header); - - foreach (var pair in values) - { - builder.AppendFormat(argFormat, pair.Key, pair.Value); - } - - builder.Append("\r\n"); - - return builder.ToString(); - } - } -} From b7c6ffe0131db74ba50fb397d43279af8f616bce Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 19 Oct 2016 02:29:00 -0400 Subject: [PATCH 7/7] handle x-png --- MediaBrowser.Model/Net/MimeTypes.cs | 1 + MediaBrowser.Providers/Manager/ImageSaver.cs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 8bf0703be..2c059c860 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -100,6 +100,7 @@ namespace MediaBrowser.Model.Net .ToDictionary(x => x.Key, x => x.First().Key, StringComparer.OrdinalIgnoreCase); dict["image/jpg"] = ".jpg"; + dict["image/x-png"] = ".png"; return dict; } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 7e1fa8984..767c034ee 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -356,6 +356,11 @@ namespace MediaBrowser.Providers.Manager var season = item as Season; var extension = MimeTypes.ToExtension(mimeType); + if (string.IsNullOrWhiteSpace(extension)) + { + throw new ArgumentException(string.Format("Unable to determine image file extension from mime type {0}", mimeType)); + } + if (type == ImageType.Thumb && saveLocally) { if (season != null && season.IndexNumber.HasValue)