浏览代码

Fix all warnings in Emby.Dlna

Bond_009 4 年之前
父节点
当前提交
170e434f92
共有 36 个文件被更改,包括 529 次插入504 次删除
  1. 1 1
      Emby.Dlna/Common/ServiceAction.cs
  2. 2 1
      Emby.Dlna/Common/StateVariable.cs
  3. 0 16
      Emby.Dlna/ConfigurationExtension.cs
  4. 4 6
      Emby.Dlna/ConnectionManager/ConnectionManagerService.cs
  5. 3 3
      Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
  6. 63 89
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  7. 23 0
      Emby.Dlna/ContentDirectory/ServerItem.cs
  8. 28 0
      Emby.Dlna/ContentDirectory/StubType.cs
  9. 3 3
      Emby.Dlna/ControlRequest.cs
  10. 1 1
      Emby.Dlna/ControlResponse.cs
  11. 26 49
      Emby.Dlna/Didl/DidlBuilder.cs
  12. 1 3
      Emby.Dlna/Didl/Filter.cs
  13. 24 0
      Emby.Dlna/DlnaConfigurationFactory.cs
  14. 9 9
      Emby.Dlna/DlnaManager.cs
  15. 1 1
      Emby.Dlna/Emby.Dlna.csproj
  16. 1 1
      Emby.Dlna/EventSubscriptionResponse.cs
  17. 10 0
      Emby.Dlna/IEventManager.cs
  18. 10 23
      Emby.Dlna/Main/DlnaEntryPoint.cs
  19. 3 3
      Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs
  20. 86 81
      Emby.Dlna/PlayTo/Device.cs
  21. 2 2
      Emby.Dlna/PlayTo/MediaChangedEventArgs.cs
  22. 108 112
      Emby.Dlna/PlayTo/PlayToController.cs
  23. 1 1
      Emby.Dlna/PlayTo/PlayToManager.cs
  24. 1 1
      Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs
  25. 1 1
      Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs
  26. 1 1
      Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
  27. 22 31
      Emby.Dlna/PlayTo/TransportCommands.cs
  28. 1 0
      Emby.Dlna/PlayTo/TransportState.cs
  29. 8 8
      Emby.Dlna/PlayTo/UpnpContainer.cs
  30. 4 3
      Emby.Dlna/PlayTo/uBaseObject.cs
  31. 58 32
      Emby.Dlna/PlayTo/uPnpNamespaces.cs
  32. 9 9
      Emby.Dlna/Service/BaseControlHandler.cs
  33. 11 9
      Emby.Dlna/Service/BaseService.cs
  34. 1 1
      Emby.Dlna/Service/ServiceXmlBuilder.cs
  35. 1 1
      Emby.Dlna/Ssdp/SsdpExtensions.cs
  36. 1 2
      Jellyfin.Api/Controllers/DlnaServerController.cs

+ 1 - 1
Emby.Dlna/Common/ServiceAction.cs

@@ -13,7 +13,7 @@ namespace Emby.Dlna.Common
 
 
         public string Name { get; set; }
         public string Name { get; set; }
 
 
-        public List<Argument> ArgumentList { get; set; }
+        public List<Argument> ArgumentList { get; }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
         public override string ToString()
         public override string ToString()

+ 2 - 1
Emby.Dlna/Common/StateVariable.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;
+using System.Collections.Generic;
 
 
 namespace Emby.Dlna.Common
 namespace Emby.Dlna.Common
 {
 {
@@ -17,7 +18,7 @@ namespace Emby.Dlna.Common
 
 
         public bool SendsEvents { get; set; }
         public bool SendsEvents { get; set; }
 
 
-        public string[] AllowedValues { get; set; }
+        public IReadOnlyList<string> AllowedValues { get; set; }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
         public override string ToString()
         public override string ToString()

+ 0 - 16
Emby.Dlna/ConfigurationExtension.cs

@@ -1,7 +1,6 @@
 #nullable enable
 #nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
-using System.Collections.Generic;
 using Emby.Dlna.Configuration;
 using Emby.Dlna.Configuration;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 
 
@@ -14,19 +13,4 @@ namespace Emby.Dlna
             return manager.GetConfiguration<DlnaOptions>("dlna");
             return manager.GetConfiguration<DlnaOptions>("dlna");
         }
         }
     }
     }
-
-    public class DlnaConfigurationFactory : IConfigurationFactory
-    {
-        public IEnumerable<ConfigurationStore> GetConfigurations()
-        {
-            return new[]
-            {
-                new ConfigurationStore
-                {
-                    Key = "dlna",
-                    ConfigurationType = typeof(DlnaOptions)
-                }
-            };
-        }
-    }
 }
 }

+ 4 - 6
Emby.Dlna/ConnectionManager/ConnectionManager.cs → Emby.Dlna/ConnectionManager/ConnectionManagerService.cs

@@ -9,22 +9,20 @@ using Microsoft.Extensions.Logging;
 
 
 namespace Emby.Dlna.ConnectionManager
 namespace Emby.Dlna.ConnectionManager
 {
 {
-    public class ConnectionManager : BaseService, IConnectionManager
+    public class ConnectionManagerService : BaseService, IConnectionManager
     {
     {
         private readonly IDlnaManager _dlna;
         private readonly IDlnaManager _dlna;
-        private readonly ILogger _logger;
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
 
 
-        public ConnectionManager(
+        public ConnectionManagerService(
             IDlnaManager dlna,
             IDlnaManager dlna,
             IServerConfigurationManager config,
             IServerConfigurationManager config,
-            ILogger<ConnectionManager> logger,
+            ILogger<ConnectionManagerService> logger,
             IHttpClient httpClient)
             IHttpClient httpClient)
             : base(logger, httpClient)
             : base(logger, httpClient)
         {
         {
             _dlna = dlna;
             _dlna = dlna;
             _config = config;
             _config = config;
-            _logger = logger;
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
@@ -39,7 +37,7 @@ namespace Emby.Dlna.ConnectionManager
             var profile = _dlna.GetProfile(request.Headers) ??
             var profile = _dlna.GetProfile(request.Headers) ??
                          _dlna.GetDefaultProfile();
                          _dlna.GetDefaultProfile();
 
 
-            return new ControlHandler(_config, _logger, profile).ProcessControlRequestAsync(request);
+            return new ControlHandler(_config, Logger, profile).ProcessControlRequestAsync(request);
         }
         }
     }
     }
 }
 }

+ 3 - 3
Emby.Dlna/ContentDirectory/ContentDirectory.cs → Emby.Dlna/ContentDirectory/ContentDirectoryService.cs

@@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging;
 
 
 namespace Emby.Dlna.ContentDirectory
 namespace Emby.Dlna.ContentDirectory
 {
 {
-    public class ContentDirectory : BaseService, IContentDirectory
+    public class ContentDirectoryService : BaseService, IContentDirectory
     {
     {
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
         private readonly IImageProcessor _imageProcessor;
         private readonly IImageProcessor _imageProcessor;
@@ -33,14 +33,14 @@ namespace Emby.Dlna.ContentDirectory
         private readonly IMediaEncoder _mediaEncoder;
         private readonly IMediaEncoder _mediaEncoder;
         private readonly ITVSeriesManager _tvSeriesManager;
         private readonly ITVSeriesManager _tvSeriesManager;
 
 
-        public ContentDirectory(
+        public ContentDirectoryService(
             IDlnaManager dlna,
             IDlnaManager dlna,
             IUserDataManager userDataManager,
             IUserDataManager userDataManager,
             IImageProcessor imageProcessor,
             IImageProcessor imageProcessor,
             ILibraryManager libraryManager,
             ILibraryManager libraryManager,
             IServerConfigurationManager config,
             IServerConfigurationManager config,
             IUserManager userManager,
             IUserManager userManager,
-            ILogger<ContentDirectory> logger,
+            ILogger<ContentDirectoryService> logger,
             IHttpClient httpClient,
             IHttpClient httpClient,
             ILocalizationManager localization,
             ILocalizationManager localization,
             IMediaSourceManager mediaSourceManager,
             IMediaSourceManager mediaSourceManager,

+ 63 - 89
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -40,6 +40,11 @@ namespace Emby.Dlna.ContentDirectory
 {
 {
     public class ControlHandler : BaseControlHandler
     public class ControlHandler : BaseControlHandler
     {
     {
+        private const string NsDc = "http://purl.org/dc/elements/1.1/";
+        private const string NsDidl = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
+        private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/";
+        private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
+
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
         private readonly IUserDataManager _userDataManager;
         private readonly IUserDataManager _userDataManager;
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
@@ -47,11 +52,6 @@ namespace Emby.Dlna.ContentDirectory
         private readonly IUserViewManager _userViewManager;
         private readonly IUserViewManager _userViewManager;
         private readonly ITVSeriesManager _tvSeriesManager;
         private readonly ITVSeriesManager _tvSeriesManager;
 
 
-        private const string NS_DC = "http://purl.org/dc/elements/1.1/";
-        private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
-        private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/";
-        private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
-
         private readonly int _systemUpdateId;
         private readonly int _systemUpdateId;
 
 
         private readonly DidlBuilder _didlBuilder;
         private readonly DidlBuilder _didlBuilder;
@@ -181,7 +181,11 @@ namespace Emby.Dlna.ContentDirectory
 
 
             userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
             userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
 
 
-            _userDataManager.SaveUserData(_user, item, userdata, UserDataSaveReason.TogglePlayed,
+            _userDataManager.SaveUserData(
+                _user,
+                item,
+                userdata,
+                UserDataSaveReason.TogglePlayed,
                 CancellationToken.None);
                 CancellationToken.None);
         }
         }
 
 
@@ -286,18 +290,17 @@ namespace Emby.Dlna.ContentDirectory
 
 
                 using (var writer = XmlWriter.Create(builder, settings))
                 using (var writer = XmlWriter.Create(builder, settings))
                 {
                 {
-                    writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
+                    writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl);
 
 
-                    writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
-                    writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
-                    writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
+                    writer.WriteAttributeString("xmlns", "dc", null, NsDc);
+                    writer.WriteAttributeString("xmlns", "dlna", null, NsDlna);
+                    writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp);
 
 
                     DidlBuilder.WriteXmlRootAttributes(_profile, writer);
                     DidlBuilder.WriteXmlRootAttributes(_profile, writer);
 
 
                     var serverItem = GetItemFromObjectId(id);
                     var serverItem = GetItemFromObjectId(id);
                     var item = serverItem.Item;
                     var item = serverItem.Item;
 
 
-
                     if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal))
                     if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal))
                     {
                     {
                         totalCount = 1;
                         totalCount = 1;
@@ -397,11 +400,11 @@ namespace Emby.Dlna.ContentDirectory
 
 
                 using (var writer = XmlWriter.Create(builder, settings))
                 using (var writer = XmlWriter.Create(builder, settings))
                 {
                 {
-                    writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
+                    writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl);
 
 
-                    writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
-                    writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
-                    writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
+                    writer.WriteAttributeString("xmlns", "dc", null, NsDc);
+                    writer.WriteAttributeString("xmlns", "dlna", null, NsDlna);
+                    writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp);
 
 
                     DidlBuilder.WriteXmlRootAttributes(_profile, writer);
                     DidlBuilder.WriteXmlRootAttributes(_profile, writer);
 
 
@@ -783,11 +786,14 @@ namespace Emby.Dlna.ContentDirectory
                 })
                 })
                 .ToArray();
                 .ToArray();
 
 
-            return ApplyPaging(new QueryResult<ServerItem>
-            {
-                Items = folders,
-                TotalRecordCount = folders.Length
-            }, startIndex, limit);
+            return ApplyPaging(
+                new QueryResult<ServerItem>
+                {
+                    Items = folders,
+                    TotalRecordCount = folders.Length
+                },
+                startIndex,
+                limit);
         }
         }
 
 
         private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
         private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
@@ -1135,14 +1141,16 @@ namespace Emby.Dlna.ContentDirectory
         {
         {
             query.OrderBy = Array.Empty<(string, SortOrder)>();
             query.OrderBy = Array.Empty<(string, SortOrder)>();
 
 
-            var items = _userViewManager.GetLatestItems(new LatestItemsQuery
-            {
-                UserId = user.Id,
-                Limit = 50,
-                IncludeItemTypes = new[] { nameof(Audio) },
-                ParentId = parent?.Id ?? Guid.Empty,
-                GroupItems = true
-            }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
+            var items = _userViewManager.GetLatestItems(
+                new LatestItemsQuery
+                {
+                    UserId = user.Id,
+                    Limit = 50,
+                    IncludeItemTypes = new[] { nameof(Audio) },
+                    ParentId = parent?.Id ?? Guid.Empty,
+                    GroupItems = true
+                },
+                query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
 
 
             return ToResult(items);
             return ToResult(items);
         }
         }
@@ -1151,12 +1159,15 @@ namespace Emby.Dlna.ContentDirectory
         {
         {
             query.OrderBy = Array.Empty<(string, SortOrder)>();
             query.OrderBy = Array.Empty<(string, SortOrder)>();
 
 
-            var result = _tvSeriesManager.GetNextUp(new NextUpQuery
-            {
-                Limit = query.Limit,
-                StartIndex = query.StartIndex,
-                UserId = query.User.Id
-            }, new[] { parent }, query.DtoOptions);
+            var result = _tvSeriesManager.GetNextUp(
+                new NextUpQuery
+                {
+                    Limit = query.Limit,
+                    StartIndex = query.StartIndex,
+                    UserId = query.User.Id
+                },
+                new[] { parent },
+                query.DtoOptions);
 
 
             return ToResult(result);
             return ToResult(result);
         }
         }
@@ -1165,14 +1176,16 @@ namespace Emby.Dlna.ContentDirectory
         {
         {
             query.OrderBy = Array.Empty<(string, SortOrder)>();
             query.OrderBy = Array.Empty<(string, SortOrder)>();
 
 
-            var items = _userViewManager.GetLatestItems(new LatestItemsQuery
-            {
-                UserId = user.Id,
-                Limit = 50,
-                IncludeItemTypes = new[] { typeof(Episode).Name },
-                ParentId = parent == null ? Guid.Empty : parent.Id,
-                GroupItems = false
-            }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
+            var items = _userViewManager.GetLatestItems(
+                new LatestItemsQuery
+                {
+                    UserId = user.Id,
+                    Limit = 50,
+                    IncludeItemTypes = new[] { typeof(Episode).Name },
+                    ParentId = parent == null ? Guid.Empty : parent.Id,
+                    GroupItems = false
+                },
+                query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
 
 
             return ToResult(items);
             return ToResult(items);
         }
         }
@@ -1183,13 +1196,14 @@ namespace Emby.Dlna.ContentDirectory
 
 
             var items = _userViewManager.GetLatestItems(
             var items = _userViewManager.GetLatestItems(
                 new LatestItemsQuery
                 new LatestItemsQuery
-            {
-                UserId = user.Id,
-                Limit = 50,
-                IncludeItemTypes = new[] { nameof(Movie) },
-                ParentId = parent?.Id ?? Guid.Empty,
-                GroupItems = true
-            }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
+                {
+                    UserId = user.Id,
+                    Limit = 50,
+                    IncludeItemTypes = new[] { nameof(Movie) },
+                    ParentId = parent?.Id ?? Guid.Empty,
+                    GroupItems = true
+                },
+                query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
 
 
             return ToResult(items);
             return ToResult(items);
         }
         }
@@ -1354,44 +1368,4 @@ namespace Emby.Dlna.ContentDirectory
             return new ServerItem(_libraryManager.GetUserRootFolder());
             return new ServerItem(_libraryManager.GetUserRootFolder());
         }
         }
     }
     }
-
-    internal class ServerItem
-    {
-        public BaseItem Item { get; set; }
-
-        public StubType? StubType { get; set; }
-
-        public ServerItem(BaseItem item)
-        {
-            Item = item;
-
-            if (item is IItemByName && !(item is Folder))
-            {
-                StubType = Dlna.ContentDirectory.StubType.Folder;
-            }
-        }
-    }
-
-    public enum StubType
-    {
-        Folder = 0,
-        Latest = 2,
-        Playlists = 3,
-        Albums = 4,
-        AlbumArtists = 5,
-        Artists = 6,
-        Songs = 7,
-        Genres = 8,
-        FavoriteSongs = 9,
-        FavoriteArtists = 10,
-        FavoriteAlbums = 11,
-        ContinueWatching = 12,
-        Movies = 13,
-        Collections = 14,
-        Favorites = 15,
-        NextUp = 16,
-        Series = 17,
-        FavoriteSeries = 18,
-        FavoriteEpisodes = 19
-    }
 }
 }

+ 23 - 0
Emby.Dlna/ContentDirectory/ServerItem.cs

@@ -0,0 +1,23 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities;
+
+namespace Emby.Dlna.ContentDirectory
+{
+    internal class ServerItem
+    {
+        public ServerItem(BaseItem item)
+        {
+            Item = item;
+
+            if (item is IItemByName && !(item is Folder))
+            {
+                StubType = Dlna.ContentDirectory.StubType.Folder;
+            }
+        }
+
+        public BaseItem Item { get; set; }
+
+        public StubType? StubType { get; set; }
+    }
+}

+ 28 - 0
Emby.Dlna/ContentDirectory/StubType.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1602
+
+namespace Emby.Dlna.ContentDirectory
+{
+    public enum StubType
+    {
+        Folder = 0,
+        Latest = 2,
+        Playlists = 3,
+        Albums = 4,
+        AlbumArtists = 5,
+        Artists = 6,
+        Songs = 7,
+        Genres = 8,
+        FavoriteSongs = 9,
+        FavoriteArtists = 10,
+        FavoriteAlbums = 11,
+        ContinueWatching = 12,
+        Movies = 13,
+        Collections = 14,
+        Favorites = 15,
+        NextUp = 16,
+        Series = 17,
+        FavoriteSeries = 18,
+        FavoriteEpisodes = 19
+    }
+}

+ 3 - 3
Emby.Dlna/ControlRequest.cs

@@ -7,12 +7,12 @@ namespace Emby.Dlna
 {
 {
     public class ControlRequest
     public class ControlRequest
     {
     {
-        public ControlRequest()
+        public ControlRequest(IHeaderDictionary headers)
         {
         {
-            Headers = new HeaderDictionary();
+            Headers = headers;
         }
         }
 
 
-        public IHeaderDictionary Headers { get; set; }
+        public IHeaderDictionary Headers { get; }
 
 
         public Stream InputXml { get; set; }
         public Stream InputXml { get; set; }
 
 

+ 1 - 1
Emby.Dlna/ControlResponse.cs

@@ -11,7 +11,7 @@ namespace Emby.Dlna
             Headers = new Dictionary<string, string>();
             Headers = new Dictionary<string, string>();
         }
         }
 
 
-        public IDictionary<string, string> Headers { get; set; }
+        public IDictionary<string, string> Headers { get; }
 
 
         public string Xml { get; set; }
         public string Xml { get; set; }
 
 

+ 26 - 49
Emby.Dlna/Didl/DidlBuilder.cs

@@ -977,12 +977,12 @@ namespace Emby.Dlna.Didl
 
 
             writer.WriteStartElement("upnp", "albumArtURI", NsUpnp);
             writer.WriteStartElement("upnp", "albumArtURI", NsUpnp);
             writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
             writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
-            writer.WriteString(albumartUrlInfo.Url);
+            writer.WriteString(albumartUrlInfo.url);
             writer.WriteFullEndElement();
             writer.WriteFullEndElement();
 
 
             // TOOD: Remove these default values
             // TOOD: Remove these default values
             var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
             var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
-            writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.Url);
+            writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
 
 
             if (!_profile.EnableAlbumArtInDidl)
             if (!_profile.EnableAlbumArtInDidl)
             {
             {
@@ -1029,8 +1029,8 @@ namespace Emby.Dlna.Didl
 
 
             // Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail
             // Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail
             // rather than using a larger one when available
             // rather than using a larger one when available
-            var width = albumartUrlInfo.Width ?? maxWidth;
-            var height = albumartUrlInfo.Height ?? maxHeight;
+            var width = albumartUrlInfo.width ?? maxWidth;
+            var height = albumartUrlInfo.height ?? maxHeight;
 
 
             var contentFeatures = new ContentFeatureBuilder(_profile)
             var contentFeatures = new ContentFeatureBuilder(_profile)
                 .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
                 .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
@@ -1047,7 +1047,7 @@ namespace Emby.Dlna.Didl
                 "resolution",
                 "resolution",
                 string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
                 string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
 
 
-            writer.WriteString(albumartUrlInfo.Url);
+            writer.WriteString(albumartUrlInfo.url);
 
 
             writer.WriteFullEndElement();
             writer.WriteFullEndElement();
         }
         }
@@ -1143,7 +1143,6 @@ namespace Emby.Dlna.Didl
 
 
             if (width == 0 || height == 0)
             if (width == 0 || height == 0)
             {
             {
-                // _imageProcessor.GetImageSize(item, imageInfo);
                 width = null;
                 width = null;
                 height = null;
                 height = null;
             }
             }
@@ -1153,18 +1152,6 @@ namespace Emby.Dlna.Didl
                 height = null;
                 height = null;
             }
             }
 
 
-            // try
-            // {
-            //    var size = _imageProcessor.GetImageSize(imageInfo);
-
-            //    width = size.Width;
-            //    height = size.Height;
-            // }
-            // catch
-            // {
-
-            // }
-
             var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
             var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
                 .TrimStart('.')
                 .TrimStart('.')
                 .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
                 .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
@@ -1181,30 +1168,6 @@ namespace Emby.Dlna.Didl
             };
             };
         }
         }
 
 
-        private class ImageDownloadInfo
-        {
-            internal Guid ItemId;
-            internal string ImageTag;
-            internal ImageType Type;
-
-            internal int? Width;
-            internal int? Height;
-
-            internal bool IsDirectStream;
-
-            internal string Format;
-
-            internal ItemImageInfo ItemImageInfo;
-        }
-
-        private class ImageUrlInfo
-        {
-            internal string Url;
-
-            internal int? Width;
-            internal int? Height;
-        }
-
         public static string GetClientId(BaseItem item, StubType? stubType)
         public static string GetClientId(BaseItem item, StubType? stubType)
         {
         {
             return GetClientId(item.Id, stubType);
             return GetClientId(item.Id, stubType);
@@ -1222,7 +1185,7 @@ namespace Emby.Dlna.Didl
             return id;
             return id;
         }
         }
 
 
-        private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
+        private (string url, int? width, int? height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
         {
         {
             var url = string.Format(
             var url = string.Format(
                 CultureInfo.InvariantCulture,
                 CultureInfo.InvariantCulture,
@@ -1260,12 +1223,26 @@ namespace Emby.Dlna.Didl
             // just lie
             // just lie
             info.IsDirectStream = true;
             info.IsDirectStream = true;
 
 
-            return new ImageUrlInfo
-            {
-                Url = url,
-                Width = width,
-                Height = height
-            };
+            return (url, width, height);
+        }
+
+        private class ImageDownloadInfo
+        {
+            internal Guid ItemId { get; set; }
+
+            internal string ImageTag { get; set; }
+
+            internal ImageType Type { get; set; }
+
+            internal int? Width { get; set; }
+
+            internal int? Height { get; set; }
+
+            internal bool IsDirectStream { get; set; }
+
+            internal string Format { get; set; }
+
+            internal ItemImageInfo ItemImageInfo { get; set; }
         }
         }
     }
     }
 }
 }

+ 1 - 3
Emby.Dlna/Didl/Filter.cs

@@ -23,9 +23,7 @@ namespace Emby.Dlna.Didl
 
 
         public bool Contains(string field)
         public bool Contains(string field)
         {
         {
-            // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back.
-            return true;
-            // return _all || ListHelper.ContainsIgnoreCase(_fields, field);
+            return _all || Array.Exists(_fields, x => x.Equals(field, StringComparison.OrdinalIgnoreCase));
         }
         }
     }
     }
 }
 }

+ 24 - 0
Emby.Dlna/DlnaConfigurationFactory.cs

@@ -0,0 +1,24 @@
+#nullable enable
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+using Emby.Dlna.Configuration;
+using MediaBrowser.Common.Configuration;
+
+namespace Emby.Dlna
+{
+    public class DlnaConfigurationFactory : IConfigurationFactory
+    {
+        public IEnumerable<ConfigurationStore> GetConfigurations()
+        {
+            return new[]
+            {
+                new ConfigurationStore
+                {
+                    Key = "dlna",
+                    ConfigurationType = typeof(DlnaOptions)
+                }
+            };
+        }
+    }
+}

+ 9 - 9
Emby.Dlna/DlnaManager.cs

@@ -495,8 +495,8 @@ namespace Emby.Dlna
         /// Recreates the object using serialization, to ensure it's not a subclass.
         /// Recreates the object using serialization, to ensure it's not a subclass.
         /// If it's a subclass it may not serlialize properly to xml (different root element tag name).
         /// If it's a subclass it may not serlialize properly to xml (different root element tag name).
         /// </summary>
         /// </summary>
-        /// <param name="profile"></param>
-        /// <returns></returns>
+        /// <param name="profile">The device profile.</param>
+        /// <returns>The reserialized device profile.</returns>
         private DeviceProfile ReserializeProfile(DeviceProfile profile)
         private DeviceProfile ReserializeProfile(DeviceProfile profile)
         {
         {
             if (profile.GetType() == typeof(DeviceProfile))
             if (profile.GetType() == typeof(DeviceProfile))
@@ -509,13 +509,6 @@ namespace Emby.Dlna
             return _jsonSerializer.DeserializeFromString<DeviceProfile>(json);
             return _jsonSerializer.DeserializeFromString<DeviceProfile>(json);
         }
         }
 
 
-        private class InternalProfileInfo
-        {
-            internal DeviceProfileInfo Info { get; set; }
-
-            internal string Path { get; set; }
-        }
-
         public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
         public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
         {
         {
             var profile = GetProfile(headers) ??
             var profile = GetProfile(headers) ??
@@ -540,6 +533,13 @@ namespace Emby.Dlna
                 Stream = _assembly.GetManifestResourceStream(resource)
                 Stream = _assembly.GetManifestResourceStream(resource)
             };
             };
         }
         }
+
+        private class InternalProfileInfo
+        {
+            internal DeviceProfileInfo Info { get; set; }
+
+            internal string Path { get; set; }
+        }
     }
     }
 
 
     /*
     /*

+ 1 - 1
Emby.Dlna/Emby.Dlna.csproj

@@ -20,7 +20,7 @@
     <TargetFramework>netstandard2.1</TargetFramework>
     <TargetFramework>netstandard2.1</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
-    <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'" >true</TreatWarningsAsErrors>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <!-- Code Analyzers-->
   <!-- Code Analyzers-->

+ 1 - 1
Emby.Dlna/EventSubscriptionResponse.cs

@@ -15,6 +15,6 @@ namespace Emby.Dlna
 
 
         public string ContentType { get; set; }
         public string ContentType { get; set; }
 
 
-        public Dictionary<string, string> Headers { get; set; }
+        public Dictionary<string, string> Headers { get; }
     }
     }
 }
 }

+ 10 - 0
Emby.Dlna/IEventManager.cs

@@ -8,16 +8,26 @@ namespace Emby.Dlna
         /// Cancels the event subscription.
         /// Cancels the event subscription.
         /// </summary>
         /// </summary>
         /// <param name="subscriptionId">The subscription identifier.</param>
         /// <param name="subscriptionId">The subscription identifier.</param>
+        /// <returns>The response.</returns>
         EventSubscriptionResponse CancelEventSubscription(string subscriptionId);
         EventSubscriptionResponse CancelEventSubscription(string subscriptionId);
 
 
         /// <summary>
         /// <summary>
         /// Renews the event subscription.
         /// Renews the event subscription.
         /// </summary>
         /// </summary>
+        /// <param name="subscriptionId">The subscription identifier.</param>
+        /// <param name="notificationType">The notification type.</param>
+        /// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
+        /// <param name="callbackUrl">The callback url.</param>
+        /// <returns>The response.</returns>
         EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl);
         EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl);
 
 
         /// <summary>
         /// <summary>
         /// Creates the event subscription.
         /// Creates the event subscription.
         /// </summary>
         /// </summary>
+        /// <param name="notificationType">The notification type.</param>
+        /// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
+        /// <param name="callbackUrl">The callback url.</param>
+        /// <returns>The response.</returns>
         EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl);
         EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl);
     }
     }
 }
 }

+ 10 - 23
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -93,14 +93,14 @@ namespace Emby.Dlna.Main
             _networkManager = networkManager;
             _networkManager = networkManager;
             _logger = loggerFactory.CreateLogger<DlnaEntryPoint>();
             _logger = loggerFactory.CreateLogger<DlnaEntryPoint>();
 
 
-            ContentDirectory = new ContentDirectory.ContentDirectory(
+            ContentDirectory = new ContentDirectory.ContentDirectoryService(
                 dlnaManager,
                 dlnaManager,
                 userDataManager,
                 userDataManager,
                 imageProcessor,
                 imageProcessor,
                 libraryManager,
                 libraryManager,
                 config,
                 config,
                 userManager,
                 userManager,
-                loggerFactory.CreateLogger<ContentDirectory.ContentDirectory>(),
+                loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(),
                 httpClient,
                 httpClient,
                 localizationManager,
                 localizationManager,
                 mediaSourceManager,
                 mediaSourceManager,
@@ -108,19 +108,19 @@ namespace Emby.Dlna.Main
                 mediaEncoder,
                 mediaEncoder,
                 tvSeriesManager);
                 tvSeriesManager);
 
 
-            ConnectionManager = new ConnectionManager.ConnectionManager(
+            ConnectionManager = new ConnectionManager.ConnectionManagerService(
                 dlnaManager,
                 dlnaManager,
                 config,
                 config,
-                loggerFactory.CreateLogger<ConnectionManager.ConnectionManager>(),
+                loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(),
                 httpClient);
                 httpClient);
 
 
-            MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(
-                loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrar>(),
+            MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService(
+                loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(),
                 httpClient,
                 httpClient,
                 config);
                 config);
             Current = this;
             Current = this;
         }
         }
-        
+
         public static DlnaEntryPoint Current { get; private set; }
         public static DlnaEntryPoint Current { get; private set; }
 
 
         public IContentDirectory ContentDirectory { get; private set; }
         public IContentDirectory ContentDirectory { get; private set; }
@@ -413,28 +413,15 @@ namespace Emby.Dlna.Main
 
 
         /// <inheritdoc />
         /// <inheritdoc />
         public void Dispose()
         public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and optionally managed resources.
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
         {
         {
             if (_disposed)
             if (_disposed)
             {
             {
                 return;
                 return;
             }
             }
 
 
-            if (disposing)
-            {
-                DisposeDevicePublisher();
-                DisposePlayToManager();
-                DisposeDeviceDiscovery();
-            }
+            DisposeDevicePublisher();
+            DisposePlayToManager();
+            DisposeDeviceDiscovery();
 
 
             if (_communicationsServer != null)
             if (_communicationsServer != null)
             {
             {

+ 3 - 3
Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs → Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs

@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
 
 
 namespace Emby.Dlna.MediaReceiverRegistrar
 namespace Emby.Dlna.MediaReceiverRegistrar
 {
 {
-    public class MediaReceiverRegistrar : BaseService, IMediaReceiverRegistrar
+    public class MediaReceiverRegistrarService : BaseService, IMediaReceiverRegistrar
     {
     {
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
 
 
-        public MediaReceiverRegistrar(
-            ILogger<MediaReceiverRegistrar> logger,
+        public MediaReceiverRegistrarService(
+            ILogger<MediaReceiverRegistrarService> logger,
             IHttpClient httpClient,
             IHttpClient httpClient,
             IServerConfigurationManager config)
             IServerConfigurationManager config)
             : base(logger, httpClient)
             : base(logger, httpClient)

+ 86 - 81
Emby.Dlna/PlayTo/Device.cs

@@ -21,15 +21,38 @@ namespace Emby.Dlna.PlayTo
     {
     {
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
 
+        private readonly IHttpClient _httpClient;
+
+        private readonly ILogger _logger;
+
+        private readonly object _timerLock = new object();
         private Timer _timer;
         private Timer _timer;
+        private int _muteVol;
+        private int _volume;
+        private DateTime _lastVolumeRefresh;
+        private bool _volumeRefreshActive;
+        private int _connectFailureCount;
+        private bool _disposed;
+
+        public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger)
+        {
+            Properties = deviceProperties;
+            _httpClient = httpClient;
+            _logger = logger;
+        }
+
+        public event EventHandler<PlaybackStartEventArgs> PlaybackStart;
+
+        public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
+
+        public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
+
+        public event EventHandler<MediaChangedEventArgs> MediaChanged;
 
 
         public DeviceInfo Properties { get; set; }
         public DeviceInfo Properties { get; set; }
 
 
-        private int _muteVol;
         public bool IsMuted { get; set; }
         public bool IsMuted { get; set; }
 
 
-        private int _volume;
-
         public int Volume
         public int Volume
         {
         {
             get
             get
@@ -53,18 +76,13 @@ namespace Emby.Dlna.PlayTo
 
 
         public bool IsStopped => TransportState == TransportState.Stopped;
         public bool IsStopped => TransportState == TransportState.Stopped;
 
 
-        private readonly IHttpClient _httpClient;
+        public Action OnDeviceUnavailable { get; set; }
 
 
-        private readonly ILogger _logger;
+        private TransportCommands AvCommands { get; set; }
 
 
-        public Action OnDeviceUnavailable { get; set; }
+        private TransportCommands RendererCommands { get; set; }
 
 
-        public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger)
-        {
-            Properties = deviceProperties;
-            _httpClient = httpClient;
-            _logger = logger;
-        }
+        public UBaseObject CurrentMediaInfo { get; private set; }
 
 
         public void Start()
         public void Start()
         {
         {
@@ -72,8 +90,6 @@ namespace Emby.Dlna.PlayTo
             _timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite);
             _timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite);
         }
         }
 
 
-        private DateTime _lastVolumeRefresh;
-        private bool _volumeRefreshActive;
         private Task RefreshVolumeIfNeeded()
         private Task RefreshVolumeIfNeeded()
         {
         {
             if (_volumeRefreshActive
             if (_volumeRefreshActive
@@ -104,7 +120,6 @@ namespace Emby.Dlna.PlayTo
             }
             }
         }
         }
 
 
-        private readonly object _timerLock = new object();
         private void RestartTimer(bool immediate = false)
         private void RestartTimer(bool immediate = false)
         {
         {
             lock (_timerLock)
             lock (_timerLock)
@@ -232,6 +247,9 @@ namespace Emby.Dlna.PlayTo
         /// <summary>
         /// <summary>
         /// Sets volume on a scale of 0-100.
         /// Sets volume on a scale of 0-100.
         /// </summary>
         /// </summary>
+        /// <param name="value">The volume on a scale of 0-100.</param>
+        /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
+        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
         public async Task SetVolume(int value, CancellationToken cancellationToken)
         public async Task SetVolume(int value, CancellationToken cancellationToken)
         {
         {
             var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
             var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
@@ -405,8 +423,6 @@ namespace Emby.Dlna.PlayTo
             RestartTimer(true);
             RestartTimer(true);
         }
         }
 
 
-        private int _connectFailureCount;
-
         private async void TimerCallback(object sender)
         private async void TimerCallback(object sender)
         {
         {
             if (_disposed)
             if (_disposed)
@@ -538,7 +554,7 @@ namespace Emby.Dlna.PlayTo
                 return;
                 return;
             }
             }
 
 
-            var volume = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i != null);
+            var volume = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i != null);
             var volumeValue = volume?.Value;
             var volumeValue = volume?.Value;
 
 
             if (string.IsNullOrWhiteSpace(volumeValue))
             if (string.IsNullOrWhiteSpace(volumeValue))
@@ -588,7 +604,7 @@ namespace Emby.Dlna.PlayTo
                 return;
                 return;
             }
             }
 
 
-            var valueNode = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetMuteResponse")
+            var valueNode = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetMuteResponse")
                                             .Select(i => i.Element("CurrentMute"))
                                             .Select(i => i.Element("CurrentMute"))
                                             .FirstOrDefault(i => i != null);
                                             .FirstOrDefault(i => i != null);
 
 
@@ -622,7 +638,7 @@ namespace Emby.Dlna.PlayTo
             }
             }
 
 
             var transportState =
             var transportState =
-                result.Document.Descendants(uPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
+                result.Document.Descendants(UPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
 
 
             var transportStateValue = transportState?.Value;
             var transportStateValue = transportState?.Value;
 
 
@@ -635,7 +651,7 @@ namespace Emby.Dlna.PlayTo
             return null;
             return null;
         }
         }
 
 
-        private async Task<uBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
+        private async Task<UBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
         {
         {
             var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
             var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
             if (command == null)
             if (command == null)
@@ -670,7 +686,7 @@ namespace Emby.Dlna.PlayTo
                 return null;
                 return null;
             }
             }
 
 
-            var e = track.Element(uPnpNamespaces.items) ?? track;
+            var e = track.Element(UPnpNamespaces.Items) ?? track;
 
 
             var elementString = (string)e;
             var elementString = (string)e;
 
 
@@ -686,13 +702,13 @@ namespace Emby.Dlna.PlayTo
                 return null;
                 return null;
             }
             }
 
 
-            e = track.Element(uPnpNamespaces.items) ?? track;
+            e = track.Element(UPnpNamespaces.Items) ?? track;
 
 
             elementString = (string)e;
             elementString = (string)e;
 
 
             if (!string.IsNullOrWhiteSpace(elementString))
             if (!string.IsNullOrWhiteSpace(elementString))
             {
             {
-                return new uBaseObject
+                return new UBaseObject
                 {
                 {
                     Url = elementString
                     Url = elementString
                 };
                 };
@@ -701,7 +717,7 @@ namespace Emby.Dlna.PlayTo
             return null;
             return null;
         }
         }
 
 
-        private async Task<(bool, uBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
+        private async Task<(bool, UBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
         {
         {
             var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
             var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
             if (command == null)
             if (command == null)
@@ -730,10 +746,10 @@ namespace Emby.Dlna.PlayTo
                 return (false, null);
                 return (false, null);
             }
             }
 
 
-            var trackUriElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null);
+            var trackUriElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null);
             var trackUri = trackUriElem?.Value;
             var trackUri = trackUriElem?.Value;
 
 
-            var durationElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null);
+            var durationElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null);
             var duration = durationElem?.Value;
             var duration = durationElem?.Value;
 
 
             if (!string.IsNullOrWhiteSpace(duration)
             if (!string.IsNullOrWhiteSpace(duration)
@@ -746,7 +762,7 @@ namespace Emby.Dlna.PlayTo
                 Duration = null;
                 Duration = null;
             }
             }
 
 
-            var positionElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null);
+            var positionElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null);
             var position = positionElem?.Value;
             var position = positionElem?.Value;
 
 
             if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
             if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
@@ -786,7 +802,7 @@ namespace Emby.Dlna.PlayTo
                 return (true, null);
                 return (true, null);
             }
             }
 
 
-            var e = uPnpResponse.Element(uPnpNamespaces.items);
+            var e = uPnpResponse.Element(UPnpNamespaces.Items);
 
 
             var uTrack = CreateUBaseObject(e, trackUri);
             var uTrack = CreateUBaseObject(e, trackUri);
 
 
@@ -827,26 +843,26 @@ namespace Emby.Dlna.PlayTo
             return null;
             return null;
         }
         }
 
 
-        private static uBaseObject CreateUBaseObject(XElement container, string trackUri)
+        private static UBaseObject CreateUBaseObject(XElement container, string trackUri)
         {
         {
             if (container == null)
             if (container == null)
             {
             {
                 throw new ArgumentNullException(nameof(container));
                 throw new ArgumentNullException(nameof(container));
             }
             }
 
 
-            var url = container.GetValue(uPnpNamespaces.Res);
+            var url = container.GetValue(UPnpNamespaces.Res);
 
 
             if (string.IsNullOrWhiteSpace(url))
             if (string.IsNullOrWhiteSpace(url))
             {
             {
                 url = trackUri;
                 url = trackUri;
             }
             }
 
 
-            return new uBaseObject
+            return new UBaseObject
             {
             {
-                Id = container.GetAttributeValue(uPnpNamespaces.Id),
-                ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId),
-                Title = container.GetValue(uPnpNamespaces.title),
-                IconUrl = container.GetValue(uPnpNamespaces.Artwork),
+                Id = container.GetAttributeValue(UPnpNamespaces.Id),
+                ParentId = container.GetAttributeValue(UPnpNamespaces.ParentId),
+                Title = container.GetValue(UPnpNamespaces.Title),
+                IconUrl = container.GetValue(UPnpNamespaces.Artwork),
                 SecondText = string.Empty,
                 SecondText = string.Empty,
                 Url = url,
                 Url = url,
                 ProtocolInfo = GetProtocolInfo(container),
                 ProtocolInfo = GetProtocolInfo(container),
@@ -861,11 +877,11 @@ namespace Emby.Dlna.PlayTo
                 throw new ArgumentNullException(nameof(container));
                 throw new ArgumentNullException(nameof(container));
             }
             }
 
 
-            var resElement = container.Element(uPnpNamespaces.Res);
+            var resElement = container.Element(UPnpNamespaces.Res);
 
 
             if (resElement != null)
             if (resElement != null)
             {
             {
-                var info = resElement.Attribute(uPnpNamespaces.ProtocolInfo);
+                var info = resElement.Attribute(UPnpNamespaces.ProtocolInfo);
 
 
                 if (info != null && !string.IsNullOrWhiteSpace(info.Value))
                 if (info != null && !string.IsNullOrWhiteSpace(info.Value))
                 {
                 {
@@ -953,11 +969,7 @@ namespace Emby.Dlna.PlayTo
             return baseUrl + url;
             return baseUrl + url;
         }
         }
 
 
-        private TransportCommands AvCommands { get; set; }
-
-        private TransportCommands RendererCommands { get; set; }
-
-        public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, CancellationToken cancellationToken)
+        public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
         {
         {
             var ssdpHttpClient = new SsdpHttpClient(httpClient);
             var ssdpHttpClient = new SsdpHttpClient(httpClient);
 
 
@@ -965,13 +977,13 @@ namespace Emby.Dlna.PlayTo
 
 
             var friendlyNames = new List<string>();
             var friendlyNames = new List<string>();
 
 
-            var name = document.Descendants(uPnpNamespaces.ud.GetName("friendlyName")).FirstOrDefault();
+            var name = document.Descendants(UPnpNamespaces.Ud.GetName("friendlyName")).FirstOrDefault();
             if (name != null && !string.IsNullOrWhiteSpace(name.Value))
             if (name != null && !string.IsNullOrWhiteSpace(name.Value))
             {
             {
                 friendlyNames.Add(name.Value);
                 friendlyNames.Add(name.Value);
             }
             }
 
 
-            var room = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault();
+            var room = document.Descendants(UPnpNamespaces.Ud.GetName("roomName")).FirstOrDefault();
             if (room != null && !string.IsNullOrWhiteSpace(room.Value))
             if (room != null && !string.IsNullOrWhiteSpace(room.Value))
             {
             {
                 friendlyNames.Add(room.Value);
                 friendlyNames.Add(room.Value);
@@ -983,74 +995,74 @@ namespace Emby.Dlna.PlayTo
                 BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port)
                 BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port)
             };
             };
 
 
-            var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault();
+            var model = document.Descendants(UPnpNamespaces.Ud.GetName("modelName")).FirstOrDefault();
             if (model != null)
             if (model != null)
             {
             {
                 deviceProperties.ModelName = model.Value;
                 deviceProperties.ModelName = model.Value;
             }
             }
 
 
-            var modelNumber = document.Descendants(uPnpNamespaces.ud.GetName("modelNumber")).FirstOrDefault();
+            var modelNumber = document.Descendants(UPnpNamespaces.Ud.GetName("modelNumber")).FirstOrDefault();
             if (modelNumber != null)
             if (modelNumber != null)
             {
             {
                 deviceProperties.ModelNumber = modelNumber.Value;
                 deviceProperties.ModelNumber = modelNumber.Value;
             }
             }
 
 
-            var uuid = document.Descendants(uPnpNamespaces.ud.GetName("UDN")).FirstOrDefault();
+            var uuid = document.Descendants(UPnpNamespaces.Ud.GetName("UDN")).FirstOrDefault();
             if (uuid != null)
             if (uuid != null)
             {
             {
                 deviceProperties.UUID = uuid.Value;
                 deviceProperties.UUID = uuid.Value;
             }
             }
 
 
-            var manufacturer = document.Descendants(uPnpNamespaces.ud.GetName("manufacturer")).FirstOrDefault();
+            var manufacturer = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturer")).FirstOrDefault();
             if (manufacturer != null)
             if (manufacturer != null)
             {
             {
                 deviceProperties.Manufacturer = manufacturer.Value;
                 deviceProperties.Manufacturer = manufacturer.Value;
             }
             }
 
 
-            var manufacturerUrl = document.Descendants(uPnpNamespaces.ud.GetName("manufacturerURL")).FirstOrDefault();
+            var manufacturerUrl = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturerURL")).FirstOrDefault();
             if (manufacturerUrl != null)
             if (manufacturerUrl != null)
             {
             {
                 deviceProperties.ManufacturerUrl = manufacturerUrl.Value;
                 deviceProperties.ManufacturerUrl = manufacturerUrl.Value;
             }
             }
 
 
-            var presentationUrl = document.Descendants(uPnpNamespaces.ud.GetName("presentationURL")).FirstOrDefault();
+            var presentationUrl = document.Descendants(UPnpNamespaces.Ud.GetName("presentationURL")).FirstOrDefault();
             if (presentationUrl != null)
             if (presentationUrl != null)
             {
             {
                 deviceProperties.PresentationUrl = presentationUrl.Value;
                 deviceProperties.PresentationUrl = presentationUrl.Value;
             }
             }
 
 
-            var modelUrl = document.Descendants(uPnpNamespaces.ud.GetName("modelURL")).FirstOrDefault();
+            var modelUrl = document.Descendants(UPnpNamespaces.Ud.GetName("modelURL")).FirstOrDefault();
             if (modelUrl != null)
             if (modelUrl != null)
             {
             {
                 deviceProperties.ModelUrl = modelUrl.Value;
                 deviceProperties.ModelUrl = modelUrl.Value;
             }
             }
 
 
-            var serialNumber = document.Descendants(uPnpNamespaces.ud.GetName("serialNumber")).FirstOrDefault();
+            var serialNumber = document.Descendants(UPnpNamespaces.Ud.GetName("serialNumber")).FirstOrDefault();
             if (serialNumber != null)
             if (serialNumber != null)
             {
             {
                 deviceProperties.SerialNumber = serialNumber.Value;
                 deviceProperties.SerialNumber = serialNumber.Value;
             }
             }
 
 
-            var modelDescription = document.Descendants(uPnpNamespaces.ud.GetName("modelDescription")).FirstOrDefault();
+            var modelDescription = document.Descendants(UPnpNamespaces.Ud.GetName("modelDescription")).FirstOrDefault();
             if (modelDescription != null)
             if (modelDescription != null)
             {
             {
                 deviceProperties.ModelDescription = modelDescription.Value;
                 deviceProperties.ModelDescription = modelDescription.Value;
             }
             }
 
 
-            var icon = document.Descendants(uPnpNamespaces.ud.GetName("icon")).FirstOrDefault();
+            var icon = document.Descendants(UPnpNamespaces.Ud.GetName("icon")).FirstOrDefault();
             if (icon != null)
             if (icon != null)
             {
             {
                 deviceProperties.Icon = CreateIcon(icon);
                 deviceProperties.Icon = CreateIcon(icon);
             }
             }
 
 
-            foreach (var services in document.Descendants(uPnpNamespaces.ud.GetName("serviceList")))
+            foreach (var services in document.Descendants(UPnpNamespaces.Ud.GetName("serviceList")))
             {
             {
                 if (services == null)
                 if (services == null)
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                var servicesList = services.Descendants(uPnpNamespaces.ud.GetName("service"));
+                var servicesList = services.Descendants(UPnpNamespaces.Ud.GetName("service"));
                 if (servicesList == null)
                 if (servicesList == null)
                 {
                 {
                     continue;
                     continue;
@@ -1077,11 +1089,11 @@ namespace Emby.Dlna.PlayTo
                 throw new ArgumentNullException(nameof(element));
                 throw new ArgumentNullException(nameof(element));
             }
             }
 
 
-            var mimeType = element.GetDescendantValue(uPnpNamespaces.ud.GetName("mimetype"));
-            var width = element.GetDescendantValue(uPnpNamespaces.ud.GetName("width"));
-            var height = element.GetDescendantValue(uPnpNamespaces.ud.GetName("height"));
-            var depth = element.GetDescendantValue(uPnpNamespaces.ud.GetName("depth"));
-            var url = element.GetDescendantValue(uPnpNamespaces.ud.GetName("url"));
+            var mimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype"));
+            var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
+            var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
+            var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth"));
+            var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url"));
 
 
             var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
             var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
             var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
             var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
@@ -1098,11 +1110,11 @@ namespace Emby.Dlna.PlayTo
 
 
         private static DeviceService Create(XElement element)
         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"));
+            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
             return new DeviceService
             {
             {
@@ -1114,14 +1126,7 @@ namespace Emby.Dlna.PlayTo
             };
             };
         }
         }
 
 
-        public event EventHandler<PlaybackStartEventArgs> PlaybackStart;
-        public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
-        public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
-        public event EventHandler<MediaChangedEventArgs> MediaChanged;
-
-        public uBaseObject CurrentMediaInfo { get; private set; }
-
-        private void UpdateMediaInfo(uBaseObject mediaInfo, TransportState state)
+        private void UpdateMediaInfo(UBaseObject mediaInfo, TransportState state)
         {
         {
             TransportState = state;
             TransportState = state;
 
 
@@ -1149,7 +1154,7 @@ namespace Emby.Dlna.PlayTo
             }
             }
         }
         }
 
 
-        private void OnPlaybackStart(uBaseObject mediaInfo)
+        private void OnPlaybackStart(UBaseObject mediaInfo)
         {
         {
             if (string.IsNullOrWhiteSpace(mediaInfo.Url))
             if (string.IsNullOrWhiteSpace(mediaInfo.Url))
             {
             {
@@ -1162,7 +1167,7 @@ namespace Emby.Dlna.PlayTo
             });
             });
         }
         }
 
 
-        private void OnPlaybackProgress(uBaseObject mediaInfo)
+        private void OnPlaybackProgress(UBaseObject mediaInfo)
         {
         {
             if (string.IsNullOrWhiteSpace(mediaInfo.Url))
             if (string.IsNullOrWhiteSpace(mediaInfo.Url))
             {
             {
@@ -1175,7 +1180,7 @@ namespace Emby.Dlna.PlayTo
             });
             });
         }
         }
 
 
-        private void OnPlaybackStop(uBaseObject mediaInfo)
+        private void OnPlaybackStop(UBaseObject mediaInfo)
         {
         {
             PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
             PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
             {
             {
@@ -1183,7 +1188,7 @@ namespace Emby.Dlna.PlayTo
             });
             });
         }
         }
 
 
-        private void OnMediaChanged(uBaseObject old, uBaseObject newMedia)
+        private void OnMediaChanged(UBaseObject old, UBaseObject newMedia)
         {
         {
             MediaChanged?.Invoke(this, new MediaChangedEventArgs
             MediaChanged?.Invoke(this, new MediaChangedEventArgs
             {
             {
@@ -1192,8 +1197,7 @@ namespace Emby.Dlna.PlayTo
             });
             });
         }
         }
 
 
-        bool _disposed;
-
+        /// <inheritdoc />
         public void Dispose()
         public void Dispose()
         {
         {
             Dispose(true);
             Dispose(true);
@@ -1222,6 +1226,7 @@ namespace Emby.Dlna.PlayTo
             _disposed = true;
             _disposed = true;
         }
         }
 
 
+        /// <inheritdoc />
         public override string ToString()
         public override string ToString()
         {
         {
             return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl);
             return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl);

+ 2 - 2
Emby.Dlna/PlayTo/MediaChangedEventArgs.cs

@@ -6,8 +6,8 @@ namespace Emby.Dlna.PlayTo
 {
 {
     public class MediaChangedEventArgs : EventArgs
     public class MediaChangedEventArgs : EventArgs
     {
     {
-        public uBaseObject OldMediaInfo { get; set; }
+        public UBaseObject OldMediaInfo { get; set; }
 
 
-        public uBaseObject NewMediaInfo { get; set; }
+        public UBaseObject NewMediaInfo { get; set; }
     }
     }
 }
 }

+ 108 - 112
Emby.Dlna/PlayTo/PlayToController.cs

@@ -377,7 +377,8 @@ namespace Emby.Dlna.PlayTo
                     _session.ApplicationVersion,
                     _session.ApplicationVersion,
                     _session.DeviceId,
                     _session.DeviceId,
                     _session.DeviceName,
                     _session.DeviceName,
-                    _session.RemoteEndPoint, user);
+                    _session.RemoteEndPoint,
+                    user);
             }
             }
 
 
             return PlayItems(playlist, cancellationToken);
             return PlayItems(playlist, cancellationToken);
@@ -502,42 +503,44 @@ namespace Emby.Dlna.PlayTo
             if (streamInfo.MediaType == DlnaProfileType.Audio)
             if (streamInfo.MediaType == DlnaProfileType.Audio)
             {
             {
                 return new ContentFeatureBuilder(profile)
                 return new ContentFeatureBuilder(profile)
-                    .BuildAudioHeader(streamInfo.Container,
-                    streamInfo.TargetAudioCodec.FirstOrDefault(),
-                    streamInfo.TargetAudioBitrate,
-                    streamInfo.TargetAudioSampleRate,
-                    streamInfo.TargetAudioChannels,
-                    streamInfo.TargetAudioBitDepth,
-                    streamInfo.IsDirectStream,
-                    streamInfo.RunTimeTicks ?? 0,
-                    streamInfo.TranscodeSeekInfo);
+                    .BuildAudioHeader(
+                        streamInfo.Container,
+                        streamInfo.TargetAudioCodec.FirstOrDefault(),
+                        streamInfo.TargetAudioBitrate,
+                        streamInfo.TargetAudioSampleRate,
+                        streamInfo.TargetAudioChannels,
+                        streamInfo.TargetAudioBitDepth,
+                        streamInfo.IsDirectStream,
+                        streamInfo.RunTimeTicks ?? 0,
+                        streamInfo.TranscodeSeekInfo);
             }
             }
 
 
             if (streamInfo.MediaType == DlnaProfileType.Video)
             if (streamInfo.MediaType == DlnaProfileType.Video)
             {
             {
                 var list = new ContentFeatureBuilder(profile)
                 var list = new ContentFeatureBuilder(profile)
-                    .BuildVideoHeader(streamInfo.Container,
-                    streamInfo.TargetVideoCodec.FirstOrDefault(),
-                    streamInfo.TargetAudioCodec.FirstOrDefault(),
-                    streamInfo.TargetWidth,
-                    streamInfo.TargetHeight,
-                    streamInfo.TargetVideoBitDepth,
-                    streamInfo.TargetVideoBitrate,
-                    streamInfo.TargetTimestamp,
-                    streamInfo.IsDirectStream,
-                    streamInfo.RunTimeTicks ?? 0,
-                    streamInfo.TargetVideoProfile,
-                    streamInfo.TargetVideoLevel,
-                    streamInfo.TargetFramerate ?? 0,
-                    streamInfo.TargetPacketLength,
-                    streamInfo.TranscodeSeekInfo,
-                    streamInfo.IsTargetAnamorphic,
-                    streamInfo.IsTargetInterlaced,
-                    streamInfo.TargetRefFrames,
-                    streamInfo.TargetVideoStreamCount,
-                    streamInfo.TargetAudioStreamCount,
-                    streamInfo.TargetVideoCodecTag,
-                    streamInfo.IsTargetAVC);
+                    .BuildVideoHeader(
+                        streamInfo.Container,
+                        streamInfo.TargetVideoCodec.FirstOrDefault(),
+                        streamInfo.TargetAudioCodec.FirstOrDefault(),
+                        streamInfo.TargetWidth,
+                        streamInfo.TargetHeight,
+                        streamInfo.TargetVideoBitDepth,
+                        streamInfo.TargetVideoBitrate,
+                        streamInfo.TargetTimestamp,
+                        streamInfo.IsDirectStream,
+                        streamInfo.RunTimeTicks ?? 0,
+                        streamInfo.TargetVideoProfile,
+                        streamInfo.TargetVideoLevel,
+                        streamInfo.TargetFramerate ?? 0,
+                        streamInfo.TargetPacketLength,
+                        streamInfo.TranscodeSeekInfo,
+                        streamInfo.IsTargetAnamorphic,
+                        streamInfo.IsTargetInterlaced,
+                        streamInfo.TargetRefFrames,
+                        streamInfo.TargetVideoStreamCount,
+                        streamInfo.TargetAudioStreamCount,
+                        streamInfo.TargetVideoCodecTag,
+                        streamInfo.IsTargetAVC);
 
 
                 return list.Count == 0 ? null : list[0];
                 return list.Count == 0 ? null : list[0];
             }
             }
@@ -681,48 +684,41 @@ namespace Emby.Dlna.PlayTo
                     case GeneralCommandType.ToggleMute:
                     case GeneralCommandType.ToggleMute:
                         return _device.ToggleMute(cancellationToken);
                         return _device.ToggleMute(cancellationToken);
                     case GeneralCommandType.SetAudioStreamIndex:
                     case GeneralCommandType.SetAudioStreamIndex:
+                        if (command.Arguments.TryGetValue("Index", out string index))
                         {
                         {
-                            if (command.Arguments.TryGetValue("Index", out string arg))
+                            if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
                             {
                             {
-                                if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var val))
-                                {
-                                    return SetAudioStreamIndex(val);
-                                }
-
-                                throw new ArgumentException("Unsupported SetAudioStreamIndex value supplied.");
+                                return SetAudioStreamIndex(val);
                             }
                             }
 
 
-                            throw new ArgumentException("SetAudioStreamIndex argument cannot be null");
+                            throw new ArgumentException("Unsupported SetAudioStreamIndex value supplied.");
                         }
                         }
+
+                        throw new ArgumentException("SetAudioStreamIndex argument cannot be null");
                     case GeneralCommandType.SetSubtitleStreamIndex:
                     case GeneralCommandType.SetSubtitleStreamIndex:
+                        if (command.Arguments.TryGetValue("Index", out index))
                         {
                         {
-                            if (command.Arguments.TryGetValue("Index", out string arg))
+                            if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
                             {
                             {
-                                if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var val))
-                                {
-                                    return SetSubtitleStreamIndex(val);
-                                }
-
-                                throw new ArgumentException("Unsupported SetSubtitleStreamIndex value supplied.");
+                                return SetSubtitleStreamIndex(val);
                             }
                             }
 
 
-                            throw new ArgumentException("SetSubtitleStreamIndex argument cannot be null");
+                            throw new ArgumentException("Unsupported SetSubtitleStreamIndex value supplied.");
                         }
                         }
+
+                        throw new ArgumentException("SetSubtitleStreamIndex argument cannot be null");
                     case GeneralCommandType.SetVolume:
                     case GeneralCommandType.SetVolume:
+                        if (command.Arguments.TryGetValue("Volume", out string vol))
                         {
                         {
-                            if (command.Arguments.TryGetValue("Volume", out string arg))
+                            if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume))
                             {
                             {
-                                if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var volume))
-                                {
-                                    return _device.SetVolume(volume, cancellationToken);
-                                }
-
-                                throw new ArgumentException("Unsupported volume value supplied.");
+                                return _device.SetVolume(volume, cancellationToken);
                             }
                             }
 
 
-                            throw new ArgumentException("Volume argument cannot be null");
+                            throw new ArgumentException("Unsupported volume value supplied.");
                         }
                         }
 
 
+                        throw new ArgumentException("Volume argument cannot be null");
                     default:
                     default:
                         return Task.CompletedTask;
                         return Task.CompletedTask;
                 }
                 }
@@ -795,6 +791,62 @@ namespace Emby.Dlna.PlayTo
             await _device.Seek(TimeSpan.FromTicks(positionTicks), cancellationToken).ConfigureAwait(false);
             await _device.Seek(TimeSpan.FromTicks(positionTicks), cancellationToken).ConfigureAwait(false);
         }
         }
 
 
+        private static int? GetIntValue(IReadOnlyDictionary<string, string> values, string name)
+        {
+            var value = values.GetValueOrDefault(name);
+
+            if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
+            {
+                return result;
+            }
+
+            return null;
+        }
+
+        private static long GetLongValue(IReadOnlyDictionary<string, string> values, string name)
+        {
+            var value = values.GetValueOrDefault(name);
+
+            if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
+            {
+                return result;
+            }
+
+            return 0;
+        }
+
+        /// <inheritdoc />
+        public Task SendMessage<T>(string name, Guid messageId, T data, CancellationToken cancellationToken)
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().Name);
+            }
+
+            if (_device == null)
+            {
+                return Task.CompletedTask;
+            }
+
+            if (string.Equals(name, "Play", StringComparison.OrdinalIgnoreCase))
+            {
+                return SendPlayCommand(data as PlayRequest, cancellationToken);
+            }
+
+            if (string.Equals(name, "PlayState", StringComparison.OrdinalIgnoreCase))
+            {
+                return SendPlaystateCommand(data as PlaystateRequest, cancellationToken);
+            }
+
+            if (string.Equals(name, "GeneralCommand", StringComparison.OrdinalIgnoreCase))
+            {
+                return SendGeneralCommand(data as GeneralCommand, cancellationToken);
+            }
+
+            // Not supported or needed right now
+            return Task.CompletedTask;
+        }
+
         private class StreamParams
         private class StreamParams
         {
         {
             private MediaSourceInfo mediaSource;
             private MediaSourceInfo mediaSource;
@@ -908,61 +960,5 @@ namespace Emby.Dlna.PlayTo
                 return request;
                 return request;
             }
             }
         }
         }
-
-        private static int? GetIntValue(IReadOnlyDictionary<string, string> values, string name)
-        {
-            var value = values.GetValueOrDefault(name);
-
-            if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
-            {
-                return result;
-            }
-
-            return null;
-        }
-
-        private static long GetLongValue(IReadOnlyDictionary<string, string> values, string name)
-        {
-            var value = values.GetValueOrDefault(name);
-
-            if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
-            {
-                return result;
-            }
-
-            return 0;
-        }
-
-        /// <inheritdoc />
-        public Task SendMessage<T>(string name, Guid messageId, T data, CancellationToken cancellationToken)
-        {
-            if (_disposed)
-            {
-                throw new ObjectDisposedException(GetType().Name);
-            }
-
-            if (_device == null)
-            {
-                return Task.CompletedTask;
-            }
-
-            if (string.Equals(name, "Play", StringComparison.OrdinalIgnoreCase))
-            {
-                return SendPlayCommand(data as PlayRequest, cancellationToken);
-            }
-
-            if (string.Equals(name, "PlayState", StringComparison.OrdinalIgnoreCase))
-            {
-                return SendPlaystateCommand(data as PlaystateRequest, cancellationToken);
-            }
-
-            if (string.Equals(name, "GeneralCommand", StringComparison.OrdinalIgnoreCase))
-            {
-                return SendGeneralCommand(data as GeneralCommand, cancellationToken);
-            }
-
-            // Not supported or needed right now
-            return Task.CompletedTask;
-        }
     }
     }
 }
 }

+ 1 - 1
Emby.Dlna/PlayTo/PlayToManager.cs

@@ -174,7 +174,7 @@ namespace Emby.Dlna.PlayTo
 
 
             if (controller == null)
             if (controller == null)
             {
             {
-                var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, cancellationToken).ConfigureAwait(false);
+                var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger, cancellationToken).ConfigureAwait(false);
 
 
                 string deviceName = device.Properties.Name;
                 string deviceName = device.Properties.Name;
 
 

+ 1 - 1
Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs

@@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
 {
 {
     public class PlaybackProgressEventArgs : EventArgs
     public class PlaybackProgressEventArgs : EventArgs
     {
     {
-        public uBaseObject MediaInfo { get; set; }
+        public UBaseObject MediaInfo { get; set; }
     }
     }
 }
 }

+ 1 - 1
Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs

@@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
 {
 {
     public class PlaybackStartEventArgs : EventArgs
     public class PlaybackStartEventArgs : EventArgs
     {
     {
-        public uBaseObject MediaInfo { get; set; }
+        public UBaseObject MediaInfo { get; set; }
     }
     }
 }
 }

+ 1 - 1
Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs

@@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
 {
 {
     public class PlaybackStoppedEventArgs : EventArgs
     public class PlaybackStoppedEventArgs : EventArgs
     {
     {
-        public uBaseObject MediaInfo { get; set; }
+        public UBaseObject MediaInfo { get; set; }
     }
     }
 }
 }

+ 22 - 31
Emby.Dlna/PlayTo/TransportCommands.cs

@@ -16,34 +16,26 @@ namespace Emby.Dlna.PlayTo
         private List<StateVariable> _stateVariables = new List<StateVariable>();
         private List<StateVariable> _stateVariables = new List<StateVariable>();
         private List<ServiceAction> _serviceActions = new List<ServiceAction>();
         private List<ServiceAction> _serviceActions = new List<ServiceAction>();
 
 
-        public List<StateVariable> StateVariables
-        {
-            get => _stateVariables;
-            set => _stateVariables = value;
-        }
+        public List<StateVariable> StateVariables => _stateVariables;
 
 
-        public List<ServiceAction> ServiceActions
-        {
-            get => _serviceActions;
-            set => _serviceActions = value;
-        }
+        public List<ServiceAction> ServiceActions => _serviceActions;
 
 
         public static TransportCommands Create(XDocument document)
         public static TransportCommands Create(XDocument document)
         {
         {
             var command = new TransportCommands();
             var command = new TransportCommands();
 
 
-            var actionList = document.Descendants(uPnpNamespaces.svc + "actionList");
+            var actionList = document.Descendants(UPnpNamespaces.Svc + "actionList");
 
 
-            foreach (var container in actionList.Descendants(uPnpNamespaces.svc + "action"))
+            foreach (var container in actionList.Descendants(UPnpNamespaces.Svc + "action"))
             {
             {
                 command.ServiceActions.Add(ServiceActionFromXml(container));
                 command.ServiceActions.Add(ServiceActionFromXml(container));
             }
             }
 
 
-            var stateValues = document.Descendants(uPnpNamespaces.ServiceStateTable).FirstOrDefault();
+            var stateValues = document.Descendants(UPnpNamespaces.ServiceStateTable).FirstOrDefault();
 
 
             if (stateValues != null)
             if (stateValues != null)
             {
             {
-                foreach (var container in stateValues.Elements(uPnpNamespaces.svc + "stateVariable"))
+                foreach (var container in stateValues.Elements(UPnpNamespaces.Svc + "stateVariable"))
                 {
                 {
                     command.StateVariables.Add(FromXml(container));
                     command.StateVariables.Add(FromXml(container));
                 }
                 }
@@ -54,19 +46,19 @@ namespace Emby.Dlna.PlayTo
 
 
         private static ServiceAction ServiceActionFromXml(XElement container)
         private static ServiceAction ServiceActionFromXml(XElement container)
         {
         {
-            var argumentList = new List<Argument>();
+            var serviceAction = new ServiceAction
+            {
+                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
+            };
+
+            var argumentList = serviceAction.ArgumentList;
 
 
-            foreach (var arg in container.Descendants(uPnpNamespaces.svc + "argument"))
+            foreach (var arg in container.Descendants(UPnpNamespaces.Svc + "argument"))
             {
             {
                 argumentList.Add(ArgumentFromXml(arg));
                 argumentList.Add(ArgumentFromXml(arg));
             }
             }
 
 
-            return new ServiceAction
-            {
-                Name = container.GetValue(uPnpNamespaces.svc + "name"),
-
-                ArgumentList = argumentList
-            };
+            return serviceAction;
         }
         }
 
 
         private static Argument ArgumentFromXml(XElement container)
         private static Argument ArgumentFromXml(XElement container)
@@ -78,29 +70,29 @@ namespace Emby.Dlna.PlayTo
 
 
             return new Argument
             return new Argument
             {
             {
-                Name = container.GetValue(uPnpNamespaces.svc + "name"),
-                Direction = container.GetValue(uPnpNamespaces.svc + "direction"),
-                RelatedStateVariable = container.GetValue(uPnpNamespaces.svc + "relatedStateVariable")
+                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
+                Direction = container.GetValue(UPnpNamespaces.Svc + "direction"),
+                RelatedStateVariable = container.GetValue(UPnpNamespaces.Svc + "relatedStateVariable")
             };
             };
         }
         }
 
 
         private static StateVariable FromXml(XElement container)
         private static StateVariable FromXml(XElement container)
         {
         {
             var allowedValues = new List<string>();
             var allowedValues = new List<string>();
-            var element = container.Descendants(uPnpNamespaces.svc + "allowedValueList")
+            var element = container.Descendants(UPnpNamespaces.Svc + "allowedValueList")
                 .FirstOrDefault();
                 .FirstOrDefault();
 
 
             if (element != null)
             if (element != null)
             {
             {
-                var values = element.Descendants(uPnpNamespaces.svc + "allowedValue");
+                var values = element.Descendants(UPnpNamespaces.Svc + "allowedValue");
 
 
                 allowedValues.AddRange(values.Select(child => child.Value));
                 allowedValues.AddRange(values.Select(child => child.Value));
             }
             }
 
 
             return new StateVariable
             return new StateVariable
             {
             {
-                Name = container.GetValue(uPnpNamespaces.svc + "name"),
-                DataType = container.GetValue(uPnpNamespaces.svc + "dataType"),
+                Name = container.GetValue(UPnpNamespaces.Svc + "name"),
+                DataType = container.GetValue(UPnpNamespaces.Svc + "dataType"),
                 AllowedValues = allowedValues.ToArray()
                 AllowedValues = allowedValues.ToArray()
             };
             };
         }
         }
@@ -183,8 +175,7 @@ namespace Emby.Dlna.PlayTo
             if (state != null)
             if (state != null)
             {
             {
                 var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
                 var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
-                                 state.AllowedValues.FirstOrDefault() ??
-                                 value;
+                    (state.AllowedValues.Count > 0 ? state.AllowedValues[0] : value);
 
 
                 return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
                 return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
             }
             }

+ 1 - 0
Emby.Dlna/PlayTo/TransportState.cs

@@ -1,4 +1,5 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
+#pragma warning disable SA1602
 
 
 namespace Emby.Dlna.PlayTo
 namespace Emby.Dlna.PlayTo
 {
 {

+ 8 - 8
Emby.Dlna/PlayTo/UpnpContainer.cs

@@ -6,22 +6,22 @@ using Emby.Dlna.Ssdp;
 
 
 namespace Emby.Dlna.PlayTo
 namespace Emby.Dlna.PlayTo
 {
 {
-    public class UpnpContainer : uBaseObject
+    public class UpnpContainer : UBaseObject
     {
     {
-        public static uBaseObject Create(XElement container)
+        public static UBaseObject Create(XElement container)
         {
         {
             if (container == null)
             if (container == null)
             {
             {
                 throw new ArgumentNullException(nameof(container));
                 throw new ArgumentNullException(nameof(container));
             }
             }
 
 
-            return new uBaseObject
+            return new UBaseObject
             {
             {
-                Id = container.GetAttributeValue(uPnpNamespaces.Id),
-                ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId),
-                Title = container.GetValue(uPnpNamespaces.title),
-                IconUrl = container.GetValue(uPnpNamespaces.Artwork),
-                UpnpClass = container.GetValue(uPnpNamespaces.uClass)
+                Id = container.GetAttributeValue(UPnpNamespaces.Id),
+                ParentId = container.GetAttributeValue(UPnpNamespaces.ParentId),
+                Title = container.GetValue(UPnpNamespaces.Title),
+                IconUrl = container.GetValue(UPnpNamespaces.Artwork),
+                UpnpClass = container.GetValue(UPnpNamespaces.Class)
             };
             };
         }
         }
     }
     }

+ 4 - 3
Emby.Dlna/PlayTo/uBaseObject.cs

@@ -1,10 +1,11 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;
+using System.Collections.Generic;
 
 
 namespace Emby.Dlna.PlayTo
 namespace Emby.Dlna.PlayTo
 {
 {
-    public class uBaseObject
+    public class UBaseObject
     {
     {
         public string Id { get; set; }
         public string Id { get; set; }
 
 
@@ -20,7 +21,7 @@ namespace Emby.Dlna.PlayTo
 
 
         public string Url { get; set; }
         public string Url { get; set; }
 
 
-        public string[] ProtocolInfo { get; set; }
+        public IReadOnlyList<string> ProtocolInfo { get; set; }
 
 
         public string UpnpClass { get; set; }
         public string UpnpClass { get; set; }
 
 
@@ -49,7 +50,7 @@ namespace Emby.Dlna.PlayTo
             }
             }
         }
         }
 
 
-        public bool Equals(uBaseObject obj)
+        public bool Equals(UBaseObject obj)
         {
         {
             if (obj == null)
             if (obj == null)
             {
             {

+ 58 - 32
Emby.Dlna/PlayTo/uPnpNamespaces.cs

@@ -4,38 +4,64 @@ using System.Xml.Linq;
 
 
 namespace Emby.Dlna.PlayTo
 namespace Emby.Dlna.PlayTo
 {
 {
-    public static class uPnpNamespaces
+    public static class UPnpNamespaces
     {
     {
-        public static XNamespace dc = "http://purl.org/dc/elements/1.1/";
-        public static XNamespace ns = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
-        public static XNamespace svc = "urn:schemas-upnp-org:service-1-0";
-        public static XNamespace ud = "urn:schemas-upnp-org:device-1-0";
-        public static XNamespace upnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
-        public static XNamespace RenderingControl = "urn:schemas-upnp-org:service:RenderingControl:1";
-        public static XNamespace AvTransport = "urn:schemas-upnp-org:service:AVTransport:1";
-        public static XNamespace ContentDirectory = "urn:schemas-upnp-org:service:ContentDirectory:1";
-
-        public static XName containers = ns + "container";
-        public static XName items = ns + "item";
-        public static XName title = dc + "title";
-        public static XName creator = dc + "creator";
-        public static XName artist = upnp + "artist";
-        public static XName Id = "id";
-        public static XName ParentId = "parentID";
-        public static XName uClass = upnp + "class";
-        public static XName Artwork = upnp + "albumArtURI";
-        public static XName Description = dc + "description";
-        public static XName LongDescription = upnp + "longDescription";
-        public static XName Album = upnp + "album";
-        public static XName Author = upnp + "author";
-        public static XName Director = upnp + "director";
-        public static XName PlayCount = upnp + "playbackCount";
-        public static XName Tracknumber = upnp + "originalTrackNumber";
-        public static XName Res = ns + "res";
-        public static XName Duration = "duration";
-        public static XName ProtocolInfo = "protocolInfo";
-
-        public static XName ServiceStateTable = svc + "serviceStateTable";
-        public static XName StateVariable = svc + "stateVariable";
+        public static XNamespace Dc { get; } = "http://purl.org/dc/elements/1.1/";
+
+        public static XNamespace Ns { get; } = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
+
+        public static XNamespace Svc { get; } = "urn:schemas-upnp-org:service-1-0";
+
+        public static XNamespace Ud { get; } = "urn:schemas-upnp-org:device-1-0";
+
+        public static XNamespace UPnp { get; } = "urn:schemas-upnp-org:metadata-1-0/upnp/";
+
+        public static XNamespace RenderingControl { get; } = "urn:schemas-upnp-org:service:RenderingControl:1";
+
+        public static XNamespace AvTransport { get; } = "urn:schemas-upnp-org:service:AVTransport:1";
+
+        public static XNamespace ContentDirectory { get; } = "urn:schemas-upnp-org:service:ContentDirectory:1";
+
+        public static XName Containers { get; } = Ns + "container";
+
+        public static XName Items { get; } = Ns + "item";
+
+        public static XName Title { get; } = Dc + "title";
+
+        public static XName Creator { get; } = Dc + "creator";
+
+        public static XName Artist { get; } = UPnp + "artist";
+
+        public static XName Id { get; } = "id";
+
+        public static XName ParentId { get; } = "parentID";
+
+        public static XName Class { get; } = UPnp + "class";
+
+        public static XName Artwork { get; } = UPnp + "albumArtURI";
+
+        public static XName Description { get; } = Dc + "description";
+
+        public static XName LongDescription { get; } = UPnp + "longDescription";
+
+        public static XName Album { get; } = UPnp + "album";
+
+        public static XName Author { get; } = UPnp + "author";
+
+        public static XName Director { get; } = UPnp + "director";
+
+        public static XName PlayCount { get; } = UPnp + "playbackCount";
+
+        public static XName Tracknumber { get; } = UPnp + "originalTrackNumber";
+
+        public static XName Res { get; } = Ns + "res";
+
+        public static XName Duration { get; } = "duration";
+
+        public static XName ProtocolInfo { get; } = "protocolInfo";
+
+        public static XName ServiceStateTable { get; } = Svc + "serviceStateTable";
+
+        public static XName StateVariable { get; } = Svc + "stateVariable";
     }
     }
 }
 }

+ 9 - 9
Emby.Dlna/Service/BaseControlHandler.cs

@@ -210,15 +210,6 @@ namespace Emby.Dlna.Service
             }
             }
         }
         }
 
 
-        private class ControlRequestInfo
-        {
-            public string LocalName { get; set; }
-
-            public string NamespaceURI { get; set; }
-
-            public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-        }
-
         protected abstract void WriteResult(string methodName, IDictionary<string, string> methodParams, XmlWriter xmlWriter);
         protected abstract void WriteResult(string methodName, IDictionary<string, string> methodParams, XmlWriter xmlWriter);
 
 
         private void LogRequest(ControlRequest request)
         private void LogRequest(ControlRequest request)
@@ -240,5 +231,14 @@ namespace Emby.Dlna.Service
 
 
             Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
             Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
         }
         }
+
+        private class ControlRequestInfo
+        {
+            public string LocalName { get; set; }
+
+            public string NamespaceURI { get; set; }
+
+            public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+        }
     }
     }
 }
 }

+ 11 - 9
Emby.Dlna/Service/BaseService.cs

@@ -8,31 +8,33 @@ namespace Emby.Dlna.Service
 {
 {
     public class BaseService : IEventManager
     public class BaseService : IEventManager
     {
     {
-        protected IEventManager _eventManager;
-        protected IHttpClient _httpClient;
-        protected ILogger Logger;
-
         protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
         protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
         {
         {
             Logger = logger;
             Logger = logger;
-            _httpClient = httpClient;
+            HttpClient = httpClient;
 
 
-            _eventManager = new EventManager(logger, _httpClient);
+            EventManager = new EventManager(logger, HttpClient);
         }
         }
 
 
+        protected IEventManager EventManager { get; }
+
+        protected IHttpClient HttpClient { get; }
+
+        protected ILogger Logger { get; }
+
         public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
         public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
         {
         {
-            return _eventManager.CancelEventSubscription(subscriptionId);
+            return EventManager.CancelEventSubscription(subscriptionId);
         }
         }
 
 
         public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl)
         public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl)
         {
         {
-            return _eventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl);
+            return EventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl);
         }
         }
 
 
         public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl)
         public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl)
         {
         {
-            return _eventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl);
+            return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl);
         }
         }
     }
     }
 }
 }

+ 1 - 1
Emby.Dlna/Service/ServiceXmlBuilder.cs

@@ -87,7 +87,7 @@ namespace Emby.Dlna.Service
                     .Append(SecurityElement.Escape(item.DataType ?? string.Empty))
                     .Append(SecurityElement.Escape(item.DataType ?? string.Empty))
                     .Append("</dataType>");
                     .Append("</dataType>");
 
 
-                if (item.AllowedValues.Length > 0)
+                if (item.AllowedValues.Count > 0)
                 {
                 {
                     builder.Append("<allowedValueList>");
                     builder.Append("<allowedValueList>");
                     foreach (var allowedValue in item.AllowedValues)
                     foreach (var allowedValue in item.AllowedValues)

+ 1 - 1
Emby.Dlna/Ssdp/Extensions.cs → Emby.Dlna/Ssdp/SsdpExtensions.cs

@@ -5,7 +5,7 @@ using System.Xml.Linq;
 
 
 namespace Emby.Dlna.Ssdp
 namespace Emby.Dlna.Ssdp
 {
 {
-    public static class Extensions
+    public static class SsdpExtensions
     {
     {
         public static string GetValue(this XElement container, XName name)
         public static string GetValue(this XElement container, XName name)
         {
         {

+ 1 - 2
Jellyfin.Api/Controllers/DlnaServerController.cs

@@ -221,9 +221,8 @@ namespace Jellyfin.Api.Controllers
 
 
         private Task<ControlResponse> ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service)
         private Task<ControlResponse> ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service)
         {
         {
-            return service.ProcessControlRequestAsync(new ControlRequest
+            return service.ProcessControlRequestAsync(new ControlRequest(Request.Headers)
             {
             {
-                Headers = Request.Headers,
                 InputXml = requestStream,
                 InputXml = requestStream,
                 TargetServerUuId = id,
                 TargetServerUuId = id,
                 RequestedUrl = GetAbsoluteUri()
                 RequestedUrl = GetAbsoluteUri()