Răsfoiți Sursa

handle dlna browse requests

Luke Pulverenti 11 ani în urmă
părinte
comite
ea182931db

+ 1 - 1
MediaBrowser.Api/BaseApiService.cs

@@ -105,7 +105,7 @@ namespace MediaBrowser.Api
         /// <param name="responseHeaders">The response headers.</param>
         /// <param name="responseHeaders">The response headers.</param>
         /// <returns>System.Object.</returns>
         /// <returns>System.Object.</returns>
         /// <exception cref="System.ArgumentNullException">cacheKey</exception>
         /// <exception cref="System.ArgumentNullException">cacheKey</exception>
-        protected object ToCachedResult<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string,string> responseHeaders = null)
+        protected object ToCachedResult<T>(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string,string> responseHeaders = null)
           where T : class
           where T : class
         {
         {
             return ResultFactory.GetCachedResult(Request, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType, responseHeaders);
             return ResultFactory.GetCachedResult(Request, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType, responseHeaders);

+ 26 - 9
MediaBrowser.Api/Dlna/DlnaServerService.cs

@@ -15,23 +15,25 @@ namespace MediaBrowser.Api.Dlna
         public string UuId { get; set; }
         public string UuId { get; set; }
     }
     }
 
 
-    [Route("/Dlna/{UuId}/contentdirectory.xml", "GET", Summary = "Gets dlna content directory xml")]
-    [Route("/Dlna/{UuId}/contentdirectory", "GET", Summary = "Gets the content directory xml")]
+    [Route("/Dlna/contentdirectory.xml", "GET", Summary = "Gets dlna content directory xml")]
+    [Route("/Dlna/contentdirectory", "GET", Summary = "Gets dlna content directory xml")]
     public class GetContentDirectory
     public class GetContentDirectory
     {
     {
-        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UuId { get; set; }
     }
     }
 
 
-    [Route("/Dlna/{UuId}/control", "POST", Summary = "Processes a control request")]
+    [Route("/Dlna/control", "POST", Summary = "Processes a control request")]
     public class ProcessControlRequest : IRequiresRequestStream
     public class ProcessControlRequest : IRequiresRequestStream
     {
     {
-        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UuId { get; set; }
-
         public Stream RequestStream { get; set; }
         public Stream RequestStream { get; set; }
     }
     }
 
 
+    [Route("/Dlna/icons/{Filename}", "GET", Summary = "Gets a server icon")]
+    public class GetIcon
+    {
+        [ApiMember(Name = "Filename", Description = "The icon filename", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+        public string Filename { get; set; }
+    }
+
     public class DlnaServerService : BaseApiService
     public class DlnaServerService : BaseApiService
     {
     {
         private readonly IDlnaManager _dlnaManager;
         private readonly IDlnaManager _dlnaManager;
@@ -72,7 +74,7 @@ namespace MediaBrowser.Api.Dlna
                     InputXml = await reader.ReadToEndAsync().ConfigureAwait(false)
                     InputXml = await reader.ReadToEndAsync().ConfigureAwait(false)
                 });
                 });
             }
             }
-        } 
+        }
 
 
         private IDictionary<string, string> GetRequestHeaders()
         private IDictionary<string, string> GetRequestHeaders()
         {
         {
@@ -85,5 +87,20 @@ namespace MediaBrowser.Api.Dlna
 
 
             return headers;
             return headers;
         }
         }
+
+        public object Get(GetIcon request)
+        {
+            using (var response = _dlnaManager.GetIcon(request.Filename))
+            {
+                using (var ms = new MemoryStream())
+                {
+                    response.Stream.CopyTo(ms);
+
+                    ms.Position = 0;
+                    var bytes = ms.ToArray();
+                    return ResultFactory.GetResult(bytes, "image/" + response.Format.ToString().ToLower());
+                }
+            }
+        }
     }
     }
 }
 }

+ 22 - 0
MediaBrowser.Controller/Dlna/DlnaIconResponse.cs

@@ -0,0 +1,22 @@
+using MediaBrowser.Controller.Drawing;
+using System;
+using System.IO;
+
+namespace MediaBrowser.Controller.Dlna
+{
+    public class DlnaIconResponse : IDisposable
+    {
+        public Stream Stream { get; set; }
+
+        public ImageFormat Format { get; set; }
+
+        public void Dispose()
+        {
+            if (Stream != null)
+            {
+                Stream.Dispose();
+                Stream = null;
+            }
+        }
+    }
+}

+ 7 - 0
MediaBrowser.Controller/Dlna/IDlnaManager.cs

@@ -77,5 +77,12 @@ namespace MediaBrowser.Controller.Dlna
         /// <param name="request">The request.</param>
         /// <param name="request">The request.</param>
         /// <returns>ControlResponse.</returns>
         /// <returns>ControlResponse.</returns>
         ControlResponse ProcessControlRequest(ControlRequest request);
         ControlResponse ProcessControlRequest(ControlRequest request);
+
+        /// <summary>
+        /// Gets the icon.
+        /// </summary>
+        /// <param name="filename">The filename.</param>
+        /// <returns>DlnaIconResponse.</returns>
+        DlnaIconResponse GetIcon(string filename);
     }
     }
 }
 }

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

@@ -79,6 +79,7 @@
     <Compile Include="Collections\CollectionCreationOptions.cs" />
     <Compile Include="Collections\CollectionCreationOptions.cs" />
     <Compile Include="Collections\ICollectionManager.cs" />
     <Compile Include="Collections\ICollectionManager.cs" />
     <Compile Include="Dlna\ControlRequest.cs" />
     <Compile Include="Dlna\ControlRequest.cs" />
+    <Compile Include="Dlna\DlnaIconResponse.cs" />
     <Compile Include="Dlna\IDlnaManager.cs" />
     <Compile Include="Dlna\IDlnaManager.cs" />
     <Compile Include="Drawing\IImageProcessor.cs" />
     <Compile Include="Drawing\IImageProcessor.cs" />
     <Compile Include="Drawing\ImageFormat.cs" />
     <Compile Include="Drawing\ImageFormat.cs" />

+ 22 - 2
MediaBrowser.Dlna/DlnaManager.cs

@@ -2,6 +2,8 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Dlna.Profiles;
 using MediaBrowser.Dlna.Profiles;
 using MediaBrowser.Dlna.Server;
 using MediaBrowser.Dlna.Server;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
@@ -23,14 +25,18 @@ namespace MediaBrowser.Dlna
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
         private readonly ILogger _logger;
         private readonly ILogger _logger;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IJsonSerializer _jsonSerializer;
+        private readonly IUserManager _userManager;
+        private readonly ILibraryManager _libraryManager;
 
 
-        public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IApplicationPaths appPaths, ILogger logger, IJsonSerializer jsonSerializer)
+        public DlnaManager(IXmlSerializer xmlSerializer, IFileSystem fileSystem, IApplicationPaths appPaths, ILogger logger, IJsonSerializer jsonSerializer, IUserManager userManager, ILibraryManager libraryManager)
         {
         {
             _xmlSerializer = xmlSerializer;
             _xmlSerializer = xmlSerializer;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
             _appPaths = appPaths;
             _appPaths = appPaths;
             _logger = logger;
             _logger = logger;
             _jsonSerializer = jsonSerializer;
             _jsonSerializer = jsonSerializer;
+            _userManager = userManager;
+            _libraryManager = libraryManager;
 
 
             //DumpProfiles();
             //DumpProfiles();
         }
         }
@@ -496,7 +502,21 @@ namespace MediaBrowser.Dlna
 
 
         public ControlResponse ProcessControlRequest(ControlRequest request)
         public ControlResponse ProcessControlRequest(ControlRequest request)
         {
         {
-            return new ControlHandler(_logger).ProcessControlRequest(request);
+            return new ControlHandler(_logger, _userManager, _libraryManager)
+                .ProcessControlRequest(request);
+        }
+
+        public DlnaIconResponse GetIcon(string filename)
+        {
+            var format = filename.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
+                ? ImageFormat.Png
+                : ImageFormat.Jpg;
+
+            return new DlnaIconResponse
+            {
+                Format = format,
+                Stream = GetType().Assembly.GetManifestResourceStream("MediaBrowser.Dlna.Images." + filename.ToLower())
+            };
         }
         }
     }
     }
 }
 }

+ 0 - 0
MediaBrowser.Dlna/Images/logo-120.jpg → MediaBrowser.Dlna/Images/logo120.jpg


+ 0 - 0
MediaBrowser.Dlna/Images/logo-120.png → MediaBrowser.Dlna/Images/logo120.png


+ 0 - 0
MediaBrowser.Dlna/Images/logo-48.jpg → MediaBrowser.Dlna/Images/logo48.jpg


+ 0 - 0
MediaBrowser.Dlna/Images/logo-48.png → MediaBrowser.Dlna/Images/logo48.png


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

@@ -147,10 +147,10 @@
     <EmbeddedResource Include="Profiles\Xml\Default.xml" />
     <EmbeddedResource Include="Profiles\Xml\Default.xml" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <EmbeddedResource Include="Images\logo-120.jpg" />
-    <EmbeddedResource Include="Images\logo-120.png" />
-    <EmbeddedResource Include="Images\logo-48.jpg" />
-    <EmbeddedResource Include="Images\logo-48.png" />
+    <EmbeddedResource Include="Images\logo120.jpg" />
+    <EmbeddedResource Include="Images\logo120.png" />
+    <EmbeddedResource Include="Images\logo48.jpg" />
+    <EmbeddedResource Include="Images\logo48.png" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 1 - 1
MediaBrowser.Dlna/Server/ContentDirectoryXmlBuilder.cs

@@ -20,7 +20,7 @@ namespace MediaBrowser.Dlna.Server
             var builder = new StringBuilder();
             var builder = new StringBuilder();
 
 
             builder.Append("<?xml version=\"1.0\"?>");
             builder.Append("<?xml version=\"1.0\"?>");
-            builder.Append("scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"");
+            builder.Append("<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">");
 
 
             builder.Append("<specVersion>");
             builder.Append("<specVersion>");
             builder.Append("<major>1</major>");
             builder.Append("<major>1</major>");

+ 395 - 27
MediaBrowser.Dlna/Server/ControlHandler.cs

@@ -1,8 +1,14 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
 using System.Text;
 using System.Text;
 using System.Xml;
 using System.Xml;
 
 
@@ -11,6 +17,9 @@ namespace MediaBrowser.Dlna.Server
     public class ControlHandler
     public class ControlHandler
     {
     {
         private readonly ILogger _logger;
         private readonly ILogger _logger;
+        private readonly IUserManager _userManager;
+        private readonly ILibraryManager _libraryManager;
+        private DeviceProfile _profile;
 
 
         private const string NS_DC = "http://purl.org/dc/elements/1.1/";
         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_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
@@ -19,14 +28,29 @@ namespace MediaBrowser.Dlna.Server
         private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
         private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
         private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
         private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
 
 
-        private const int systemID = 0;
+        private int systemID = 0;
+        private readonly CultureInfo _usCulture = new CultureInfo("en-US");
 
 
-        public ControlHandler(ILogger logger)
+        public ControlHandler(ILogger logger, IUserManager userManager, ILibraryManager libraryManager)
         {
         {
             _logger = logger;
             _logger = logger;
+            _userManager = userManager;
+            _libraryManager = libraryManager;
         }
         }
 
 
         public ControlResponse ProcessControlRequest(ControlRequest request)
         public ControlResponse ProcessControlRequest(ControlRequest request)
+        {
+            try
+            {
+                return ProcessControlRequestInternal(request);
+            }
+            catch (Exception ex)
+            {
+                return GetErrorResponse(ex);
+            }
+        }
+
+        private ControlResponse ProcessControlRequestInternal(ControlRequest request)
         {
         {
             var soap = new XmlDocument();
             var soap = new XmlDocument();
             soap.LoadXml(request.InputXml);
             soap.LoadXml(request.InputXml);
@@ -55,6 +79,11 @@ namespace MediaBrowser.Dlna.Server
             env.DocumentElement.AppendChild(rbody);
             env.DocumentElement.AppendChild(rbody);
 
 
             IEnumerable<KeyValuePair<string, string>> result;
             IEnumerable<KeyValuePair<string, string>> result;
+
+            _logger.Debug("Received control request {0}", method.Name);
+
+            var user = _userManager.Users.First();
+
             switch (method.LocalName)
             switch (method.LocalName)
             {
             {
                 case "GetSearchCapabilities":
                 case "GetSearchCapabilities":
@@ -67,13 +96,13 @@ namespace MediaBrowser.Dlna.Server
                     result = HandleGetSystemUpdateID();
                     result = HandleGetSystemUpdateID();
                     break;
                     break;
                 case "Browse":
                 case "Browse":
-                    result = HandleBrowse(sparams);
+                    result = HandleBrowse(sparams, user);
                     break;
                     break;
                 case "X_GetFeatureList":
                 case "X_GetFeatureList":
                     result = HandleXGetFeatureList();
                     result = HandleXGetFeatureList();
                     break;
                     break;
                 case "X_SetBookmark":
                 case "X_SetBookmark":
-                    result = HandleXSetBookmark(sparams);
+                    result = HandleXSetBookmark(sparams, user);
                     break;
                     break;
                 default:
                 default:
                     throw new ResourceNotFoundException();
                     throw new ResourceNotFoundException();
@@ -99,41 +128,60 @@ namespace MediaBrowser.Dlna.Server
             return controlResponse;
             return controlResponse;
         }
         }
 
 
-        private Headers HandleXSetBookmark(Headers sparams)
+        private ControlResponse GetErrorResponse(Exception ex)
+        {
+            var env = new XmlDocument();
+            env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", "yes"));
+            var envelope = env.CreateElement("SOAP-ENV", "Envelope", NS_SOAPENV);
+            env.AppendChild(envelope);
+            envelope.SetAttribute("encodingStyle", NS_SOAPENV, "http://schemas.xmlsoap.org/soap/encoding/");
+
+            var rbody = env.CreateElement("SOAP-ENV:Body", NS_SOAPENV);
+            env.DocumentElement.AppendChild(rbody);
+
+            var fault = env.CreateElement("SOAP-ENV", "Fault", NS_SOAPENV);
+            var faultCode = env.CreateElement("faultcode");
+            faultCode.InnerText = "500";
+            fault.AppendChild(faultCode);
+            var faultString = env.CreateElement("faultstring");
+            faultString.InnerText = ex.ToString();
+            fault.AppendChild(faultString);
+            var detail = env.CreateDocumentFragment();
+            detail.InnerXml = "<detail><UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\"><errorCode>401</errorCode><errorDescription>Invalid Action</errorDescription></UPnPError></detail>";
+            fault.AppendChild(detail);
+            rbody.AppendChild(fault);
+
+            return new ControlResponse
+            {
+                Xml = env.OuterXml
+            };
+        }
+
+        private IEnumerable<KeyValuePair<string, string>> HandleXSetBookmark(IDictionary<string, string> sparams, User user)
         {
         {
             var id = sparams["ObjectID"];
             var id = sparams["ObjectID"];
-            //var item = GetItem(id) as IBookmarkable;
-            //if (item != null)
-            //{
-            //    var newbookmark = long.Parse(sparams["PosSecond"]);
-            //    if (newbookmark > 30)
-            //    {
-            //        newbookmark -= 5;
-            //    }
-            //    if (newbookmark > 30 || !item.Bookmark.HasValue || item.Bookmark.Value < 60)
-            //    {
-            //        item.Bookmark = newbookmark;
-            //    }
-            //}
+
+            var newbookmark = long.Parse(sparams["PosSecond"]);
+
             return new Headers();
             return new Headers();
         }
         }
 
 
-        private Headers HandleGetSearchCapabilities()
+        private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities()
         {
         {
             return new Headers { { "SearchCaps", string.Empty } };
             return new Headers { { "SearchCaps", string.Empty } };
         }
         }
 
 
-        private Headers HandleGetSortCapabilities()
+        private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities()
         {
         {
             return new Headers { { "SortCaps", string.Empty } };
             return new Headers { { "SortCaps", string.Empty } };
         }
         }
 
 
-        private Headers HandleGetSystemUpdateID()
+        private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID()
         {
         {
-            return new Headers { { "Id", systemID.ToString() } };
+            return new Headers { { "Id", systemID.ToString(_usCulture) } };
         }
         }
 
 
-        private Headers HandleXGetFeatureList()
+        private IEnumerable<KeyValuePair<string, string>> HandleXGetFeatureList()
         {
         {
             return new Headers { { "FeatureList", GetFeatureListXml() } };
             return new Headers { { "FeatureList", GetFeatureListXml() } };
         }
         }
@@ -156,14 +204,14 @@ namespace MediaBrowser.Dlna.Server
             return builder.ToString();
             return builder.ToString();
         }
         }
 
 
-        private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams)
+        private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams, User user)
         {
         {
             var id = sparams["ObjectID"];
             var id = sparams["ObjectID"];
             var flag = sparams["BrowseFlag"];
             var flag = sparams["BrowseFlag"];
 
 
-            int requested;
+            int requested = 20;
             var provided = 0;
             var provided = 0;
-            int start;
+            int start = 0;
 
 
             if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
             if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
             {
             {
@@ -184,7 +232,327 @@ namespace MediaBrowser.Dlna.Server
             didl.SetAttribute("xmlns:sec", NS_SEC);
             didl.SetAttribute("xmlns:sec", NS_SEC);
             result.AppendChild(didl);
             result.AppendChild(didl);
 
 
-            return null;
+            var folder = string.IsNullOrWhiteSpace(id)
+                ? user.RootFolder
+                : (Folder)_libraryManager.GetItemById(new Guid(id));
+
+            var children = folder.GetChildren(user, true).ToList();
+
+            if (string.Equals(flag, "BrowseMetadata"))
+            {
+                Browse_AddFolder(result, folder, children.Count);
+                provided++;
+            }
+            else
+            {
+                foreach (var i in children.OfType<Folder>())
+                {
+                    if (start > 0)
+                    {
+                        start--;
+                        continue;
+                    }
+
+                    var childCount = i.GetChildren(user, true).Count();
+
+                    Browse_AddFolder(result, i, childCount);
+
+                    if (++provided == requested)
+                    {
+                        break;
+                    }
+                }
+
+                if (provided != requested)
+                {
+                    foreach (var i in children.Where(i => !i.IsFolder))
+                    {
+                        if (start > 0)
+                        {
+                            start--;
+                            continue;
+                        }
+
+                        Browse_AddItem(result, i, user);
+
+                        if (++provided == requested)
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            var resXML = result.OuterXml;
+
+            return new List<KeyValuePair<string, string>>
+            {
+                new KeyValuePair<string,string>("Result", resXML),
+                new KeyValuePair<string,string>("NumberReturned", provided.ToString(_usCulture)),
+                new KeyValuePair<string,string>("TotalMatches", children.Count.ToString(_usCulture)),
+                new KeyValuePair<string,string>("UpdateID", systemID.ToString(_usCulture))
+            };
+        }
+
+        private void Browse_AddFolder(XmlDocument result, Folder f, int childCount)
+        {
+            var container = result.CreateElement(string.Empty, "container", NS_DIDL);
+            container.SetAttribute("restricted", "0");
+            container.SetAttribute("childCount", childCount.ToString(_usCulture));
+            container.SetAttribute("id", f.Id.ToString("N"));
+
+            var parent = f.Parent;
+            if (parent == null)
+            {
+                container.SetAttribute("parentID", "0");
+            }
+            else
+            {
+                container.SetAttribute("parentID", parent.Id.ToString("N"));
+            }
+
+            var title = result.CreateElement("dc", "title", NS_DC);
+            title.InnerText = f.Name;
+            container.AppendChild(title);
+
+            var date = result.CreateElement("dc", "date", NS_DC);
+            date.InnerText = f.DateModified.ToString("o");
+            container.AppendChild(date);
+
+            var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
+            objectClass.InnerText = "object.container.storageFolder";
+            container.AppendChild(objectClass);
+            result.DocumentElement.AppendChild(container);
+        }
+
+        private void Browse_AddItem(XmlDocument result, BaseItem item, User user)
+        {
+            var element = result.CreateElement(string.Empty, "item", NS_DIDL);
+            element.SetAttribute("restricted", "1");
+            element.SetAttribute("id", item.Id.ToString("N"));
+
+            if (item.Parent != null)
+            {
+                element.SetAttribute("parentID", item.Parent.Id.ToString("N"));
+            }
+
+            element.AppendChild(CreateObjectClass(result, item));
+
+            AddBookmarkInfo(item, user, element);
+
+            AddGeneralProperties(item, element);
+
+            AddActors(item, element);
+
+            var title = result.CreateElement("dc", "title", NS_DC);
+            title.InnerText = item.Name;
+            element.AppendChild(title);
+
+            var res = result.CreateElement(string.Empty, "res", NS_DIDL);
+
+            //res.InnerText = String.Format(
+            //  "http://{0}:{1}{2}file/{3}",
+            //  request.LocalEndPoint.Address,
+            //  request.LocalEndPoint.Port,
+            //  prefix,
+            //  resource.Id
+            //  );
+
+            //if (props.TryGetValue("SizeRaw", out prop))
+            //{
+            //    res.SetAttribute("size", prop);
+            //}
+            //if (props.TryGetValue("Resolution", out prop))
+            //{
+            //    res.SetAttribute("resolution", prop);
+            //}
+            //if (props.TryGetValue("Duration", out prop))
+            //{
+            //    res.SetAttribute("duration", prop);
+            //}
+
+            //res.SetAttribute("protocolInfo", String.Format(
+            //    "http-get:*:{1}:{0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}",
+            //    resource.PN, DlnaMaps.Mime[resource.Type], DlnaMaps.DefaultStreaming
+            //    ));
+
+            element.AppendChild(res);
+
+            AddCover(item, element);
+
+            result.DocumentElement.AppendChild(element);
+        }
+
+        private XmlElement CreateObjectClass(XmlDocument result, BaseItem item)
+        {
+            var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
+
+            if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
+            {
+                objectClass.InnerText = "object.item.audioItem.musicTrack";
+            }
+            else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase))
+            {
+                objectClass.InnerText = "object.item.imageItem.photo";
+            }
+            else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+            {
+                objectClass.InnerText = "object.item.videoItem.movie";
+            }
+            else
+            {
+                throw new NotSupportedException();
+            }
+
+            return objectClass;
+        }
+
+        private void AddActors(BaseItem item, XmlElement element)
+        {
+            foreach (var actor in item.People)
+            {
+                var e = element.OwnerDocument.CreateElement("upnp", "actor", NS_UPNP);
+                e.InnerText = actor.Name;
+                element.AppendChild(e);
+            }
+        }
+
+        private void AddBookmarkInfo(BaseItem item, User user, XmlElement element)
+        {
+            //var bookmark = bookmarkable.Bookmark;
+            //if (bookmark.HasValue)
+            //{
+            //    var dcmInfo = item.OwnerDocument.CreateElement("sec", "dcmInfo", NS_SEC);
+            //    dcmInfo.InnerText = string.Format("BM={0}", bookmark.Value);
+            //    item.AppendChild(dcmInfo);
+            //}
+        }
+
+        private  void AddGeneralProperties(BaseItem item, XmlElement element)
+        {
+            //var prop = string.Empty;
+            //if (props.TryGetValue("DateO", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("dc", "date", NS_DC);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+            //if (props.TryGetValue("Genre", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "genre", NS_UPNP);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+
+            if (!string.IsNullOrWhiteSpace(item.Overview))
+            {
+                var e = element.OwnerDocument.CreateElement("dc", "description", NS_DC);
+                e.InnerText = item.Overview;
+                element.AppendChild(e);
+            }
+
+            //if (props.TryGetValue("Artist", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "artist", NS_UPNP);
+            //    e.SetAttribute("role", "AlbumArtist");
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+            //if (props.TryGetValue("Performer", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "artist", NS_UPNP);
+            //    e.SetAttribute("role", "Performer");
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //    e = item.OwnerDocument.CreateElement("dc", "creator", NS_DC);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+            //if (props.TryGetValue("Album", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "album", NS_UPNP);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+            //if (props.TryGetValue("Track", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "originalTrackNumber", NS_UPNP);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+            //if (props.TryGetValue("Creator", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("dc", "creator", NS_DC);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+
+            //if (props.TryGetValue("Director", out prop))
+            //{
+            //    var e = item.OwnerDocument.CreateElement("upnp", "director", NS_UPNP);
+            //    e.InnerText = prop;
+            //    item.AppendChild(e);
+            //}
+        }
+
+        private void AddCover(BaseItem item, XmlElement element)
+        {
+            //var result = item.OwnerDocument;
+            //var cover = resource as IMediaCover;
+            //if (cover == null)
+            //{
+            //    return;
+            //}
+            //try
+            //{
+            //    var c = cover.Cover;
+            //    var curl = String.Format(
+            //      "http://{0}:{1}{2}cover/{3}",
+            //      request.LocalEndPoint.Address,
+            //      request.LocalEndPoint.Port,
+            //      prefix,
+            //      resource.Id
+            //      );
+            //    var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP);
+            //    var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
+            //    profile.InnerText = "JPEG_TN";
+            //    icon.SetAttributeNode(profile);
+            //    icon.InnerText = curl;
+            //    item.AppendChild(icon);
+            //    icon = result.CreateElement("upnp", "icon", NS_UPNP);
+            //    profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
+            //    profile.InnerText = "JPEG_TN";
+            //    icon.SetAttributeNode(profile);
+            //    icon.InnerText = curl;
+            //    item.AppendChild(icon);
+
+            //    var res = result.CreateElement(string.Empty, "res", NS_DIDL);
+            //    res.InnerText = curl;
+
+            //    res.SetAttribute("protocolInfo", string.Format(
+            //        "http-get:*:{1}:{0};DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS={2}",
+            //        c.PN, DlnaMaps.Mime[c.Type], DlnaMaps.DefaultStreaming
+            //        ));
+            //    var width = c.MetaWidth;
+            //    var height = c.MetaHeight;
+            //    if (width.HasValue && height.HasValue)
+            //    {
+            //        res.SetAttribute("resolution", string.Format("{0}x{1}", width.Value, height.Value));
+            //    }
+            //    else
+            //    {
+            //        res.SetAttribute("resolution", "200x200");
+            //    }
+            //    res.SetAttribute("protocolInfo", string.Format(
+            //      "http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS={0}",
+            //      DlnaMaps.DefaultInteractive
+            //      ));
+            //    item.AppendChild(res);
+            //}
+            //catch (Exception)
+            //{
+            //    return;
+            //}
         }
         }
     }
     }
 }
 }

+ 11 - 11
MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs

@@ -130,11 +130,11 @@ namespace MediaBrowser.Dlna.Server
 
 
             list.Add(new DeviceIcon
             list.Add(new DeviceIcon
             {
             {
-                MimeType = "image/jpeg",
+                MimeType = "image/png",
                 Depth = "24",
                 Depth = "24",
-                Width = 48,
-                Height = 48,
-                Url = "/mediabrowser/dlna/icons/small.jpg"
+                Width = 120,
+                Height = 120,
+                Url = "/mediabrowser/dlna/icons/logo120.png"
             });
             });
 
 
             list.Add(new DeviceIcon
             list.Add(new DeviceIcon
@@ -143,7 +143,7 @@ namespace MediaBrowser.Dlna.Server
                 Depth = "24",
                 Depth = "24",
                 Width = 120,
                 Width = 120,
                 Height = 120,
                 Height = 120,
-                Url = "/mediabrowser/dlna/icons/large.jpg"
+                Url = "/mediabrowser/dlna/icons/logo120.jpg"
             });
             });
 
 
             list.Add(new DeviceIcon
             list.Add(new DeviceIcon
@@ -152,16 +152,16 @@ namespace MediaBrowser.Dlna.Server
                 Depth = "24",
                 Depth = "24",
                 Width = 48,
                 Width = 48,
                 Height = 48,
                 Height = 48,
-                Url = "/mediabrowser/dlna/icons/small.png"
+                Url = "/mediabrowser/dlna/icons/logo48.png"
             });
             });
 
 
             list.Add(new DeviceIcon
             list.Add(new DeviceIcon
             {
             {
-                MimeType = "image/png",
+                MimeType = "image/jpeg",
                 Depth = "24",
                 Depth = "24",
-                Width = 120,
-                Height = 120,
-                Url = "/mediabrowser/dlna/icons/large.png"
+                Width = 48,
+                Height = 48,
+                Url = "/mediabrowser/dlna/icons/logo48.jpg"
             });
             });
             
             
             return list;
             return list;
@@ -176,7 +176,7 @@ namespace MediaBrowser.Dlna.Server
                 ServiceType = "urn:schemas-upnp-org:service:ContentDirectory:1",
                 ServiceType = "urn:schemas-upnp-org:service:ContentDirectory:1",
                 ServiceId = "urn:upnp-org:serviceId:ContentDirectory",
                 ServiceId = "urn:upnp-org:serviceId:ContentDirectory",
                 ScpdUrl = "/mediabrowser/dlna/contentdirectory.xml",
                 ScpdUrl = "/mediabrowser/dlna/contentdirectory.xml",
-                ControlUrl = "/servicecontrol"
+                ControlUrl = "/mediabrowser/dlna/control"
             });
             });
 
 
             return list;
             return list;

+ 7 - 0
MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj

@@ -80,6 +80,13 @@
     <None Include="packages.config" />
     <None Include="packages.config" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   <Target Name="BeforeBuild">

+ 1 - 1
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -506,7 +506,7 @@ namespace MediaBrowser.ServerApplication
             var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
             var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
             RegisterSingleInstance<IAppThemeManager>(appThemeManager);
             RegisterSingleInstance<IAppThemeManager>(appThemeManager);
 
 
-            var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LogManager.GetLogger("DLNA"), JsonSerializer);
+            var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LogManager.GetLogger("DLNA"), JsonSerializer, UserManager, LibraryManager);
             RegisterSingleInstance<IDlnaManager>(dlnaManager);
             RegisterSingleInstance<IDlnaManager>(dlnaManager);
 
 
             var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);
             var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);