Преглед изворни кода

Merge pull request #2244 from MediaBrowser/dev

Dev
Luke пре 8 година
родитељ
комит
b9c64d7e8d
27 измењених фајлова са 154 додато и 593 уклоњено
  1. 13 0
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  2. 0 8
      MediaBrowser.Controller/Dlna/ISsdpHandler.cs
  3. 0 1
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  4. 21 1
      MediaBrowser.Dlna/Didl/DidlBuilder.cs
  5. 49 24
      MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
  6. 0 4
      MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
  7. 0 126
      MediaBrowser.Dlna/Ssdp/Datagram.cs
  8. 0 21
      MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs
  9. 0 24
      MediaBrowser.Dlna/Ssdp/Extensions.cs
  10. 0 328
      MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
  11. 0 26
      MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs
  12. 1 0
      MediaBrowser.Model/LiveTv/LiveTvOptions.cs
  13. 1 0
      MediaBrowser.Model/LiveTv/ProgramQuery.cs
  14. 1 0
      MediaBrowser.Model/Net/MimeTypes.cs
  15. 5 0
      MediaBrowser.Providers/Manager/ImageSaver.cs
  16. 5 1
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  17. 0 1
      MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
  18. 6 1
      MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
  19. 1 1
      MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
  20. 6 3
      MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
  21. 34 9
      MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
  22. 5 2
      MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs
  23. 1 1
      MediaBrowser.ServerApplication/MainStartup.cs
  24. 0 6
      MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
  25. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  26. 1 1
      Nuget/MediaBrowser.Common.nuspec
  27. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 13 - 0
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; }
 
         /// <summary>
         /// 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);

+ 0 - 8
MediaBrowser.Controller/Dlna/ISsdpHandler.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace MediaBrowser.Controller.Dlna
-{
-    public interface ISsdpHandler
-    {
-    }
-}

+ 0 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -111,7 +111,6 @@
     <Compile Include="Dlna\IDlnaManager.cs" />
     <Compile Include="Dlna\IEventManager.cs" />
     <Compile Include="Dlna\IMediaReceiverRegistrar.cs" />
-    <Compile Include="Dlna\ISsdpHandler.cs" />
     <Compile Include="Dlna\IUpnpService.cs" />
     <Compile Include="Dlna\SsdpMessageEventArgs.cs" />
     <Compile Include="Drawing\IImageProcessor.cs" />

+ 21 - 1
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;
+                }
             }
         }
 

+ 49 - 24
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<string>
+                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<string>
                 {
-                    "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()
         {

+ 0 - 4
MediaBrowser.Dlna/MediaBrowser.Dlna.csproj

@@ -108,7 +108,6 @@
     <Compile Include="Profiles\SonyBravia2014Profile.cs" />
     <Compile Include="Profiles\SonyPs4Profile.cs" />
     <Compile Include="Profiles\VlcProfile.cs" />
-    <Compile Include="Ssdp\DeviceDiscoveryInfo.cs" />
     <Compile Include="Ssdp\Extensions.cs" />
     <Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
     <Compile Include="PlayTo\PlaybackStoppedEventArgs.cs" />
@@ -130,7 +129,6 @@
     <Compile Include="Service\BaseService.cs" />
     <Compile Include="Service\ControlErrorHandler.cs" />
     <Compile Include="Service\ServiceXmlBuilder.cs" />
-    <Compile Include="Ssdp\Datagram.cs" />
     <Compile Include="Server\DescriptionXmlBuilder.cs" />
     <Compile Include="Ssdp\DeviceDiscovery.cs" />
     <Compile Include="PlayTo\SsdpHttpClient.cs" />
@@ -160,8 +158,6 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Server\Headers.cs" />
     <Compile Include="Server\UpnpDevice.cs" />
-    <Compile Include="Ssdp\SsdpMessageBuilder.cs" />
-    <Compile Include="Ssdp\SsdpHandler.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">

+ 0 - 126
MediaBrowser.Dlna/Ssdp/Datagram.cs

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

+ 0 - 21
MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs

@@ -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; }
-
-        /// <summary>
-        /// The server's ip address that the device responded to
-        /// </summary>
-        public IPAddress LocalIpAddress { get; set; }
-
-        public Uri Uri { get; set; }
-
-        public string Usn { get; set; }
-        public string Nt { get; set; }
-    }
-}

+ 0 - 24
MediaBrowser.Dlna/Ssdp/Extensions.cs

@@ -9,30 +9,6 @@ namespace MediaBrowser.Dlna.Ssdp
 {
     public static class Extensions
     {
-        public static Task<int> ReceiveAsync(this Socket socket, byte[] buffer, int offset, int size)
-        {
-            var tcs = new TaskCompletionSource<int>(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<int>)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);

+ 0 - 328
MediaBrowser.Dlna/Ssdp/SsdpHandler.cs

@@ -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<string, List<UpnpDevice>> _devices = new Dictionary<string, List<UpnpDevice>>();
-
-        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<UpnpDevice> 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<string, string>(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<string> services)
-        {
-            lock (_devices)
-            {
-                List<UpnpDevice> list;
-                List<UpnpDevice> dl;
-                if (_devices.TryGetValue(uuid, out dl))
-                {
-                    list = dl;
-                }
-                else
-                {
-                    list = new List<UpnpDevice>();
-                    _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<UpnpDevice> 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;
-        }
-    }
-}

+ 0 - 26
MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs

@@ -1,26 +0,0 @@
-using System.Collections.Generic;
-using System.Text;
-
-namespace MediaBrowser.Dlna.Ssdp
-{
-    public class SsdpMessageBuilder
-    {
-        public string BuildMessage(string header, Dictionary<string, string> 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();
-        }
-    }
-}

+ 1 - 0
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<TunerHostInfo> TunerHosts { get; set; }
         public List<ListingsProviderInfo> ListingProviders { get; set; }

+ 1 - 0
MediaBrowser.Model/LiveTv/ProgramQuery.cs

@@ -42,6 +42,7 @@ namespace MediaBrowser.Model.LiveTv
         /// <value>The user identifier.</value>
         public string UserId { get; set; }
         public string SeriesTimerId { get; set; }
+        public string Name { get; set; }
 
         /// <summary>
         /// The earliest date for which a program starts to return

+ 1 - 0
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;
         }

+ 5 - 0
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)

+ 5 - 1
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

+ 0 - 1
MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs

@@ -360,7 +360,6 @@ namespace MediaBrowser.Server.Implementations.Library
 
         public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken)
         {
-            enableAutoClose = false;
             await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
 
             try

+ 6 - 1
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<MediaStream>();
             return !mediaStreams.Any(i => i.Type == MediaStreamType.Video && string.Equals(i.Codec, "h264", StringComparison.OrdinalIgnoreCase) && !i.IsInterlaced);
         }

+ 1 - 1
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
             };
 
@@ -2304,7 +2305,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<DayOfWeek>
             {

+ 6 - 3
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<IEnumerable<ChannelInfo>> 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<List<LiveTvTunerInfo>> 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))
             {
 
             }

+ 34 - 9
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<List<M3UChannel>> 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));
         }
@@ -111,15 +120,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 +155,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
                     return match.Groups[2].Value;
                 }
             }
-            return defaultResult;
+            return null;
         }
     }
 

+ 5 - 2
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);

+ 1 - 1
MediaBrowser.ServerApplication/MainStartup.cs

@@ -71,7 +71,7 @@ namespace MediaBrowser.ServerApplication
 
             if (_isRunningAsService)
             {
-                _canRestartService = CanRestartWindowsService();
+                //_canRestartService = CanRestartWindowsService();
             }
 
             var currentProcess = Process.GetCurrentProcess();

+ 0 - 6
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -986,9 +986,6 @@
     <Content Include="dashboard-ui\scripts\userparentalcontrol.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="dashboard-ui\scripts\wizardservice.js">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
     <Content Include="dashboard-ui\scripts\wizardsettings.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
@@ -1034,9 +1031,6 @@
     <Content Include="dashboard-ui\wizardlivetvtuner.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="dashboard-ui\wizardservice.html">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
     <Content Include="dashboard-ui\wizardsettings.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>

+ 2 - 2
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.663</version>
+        <version>3.0.664</version>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.663" />
+            <dependency id="MediaBrowser.Common" version="3.0.664" />
             <dependency id="NLog" version="4.3.8" />
             <dependency id="SimpleInjector" version="3.2.2" />
         </dependencies>

+ 1 - 1
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.663</version>
+        <version>3.0.664</version>
         <title>MediaBrowser.Common</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
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.663</version>
+        <version>3.0.664</version>
         <title>Media Browser.Server.Core</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Emby Server.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.663" />
+            <dependency id="MediaBrowser.Common" version="3.0.664" />
 			<dependency id="Interfaces.IO" version="1.0.0.5" />
         </dependencies>
     </metadata>