TransportCommands.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma warning disable CS1591
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Xml.Linq;
  7. using Emby.Dlna.Common;
  8. using Emby.Dlna.Ssdp;
  9. namespace Emby.Dlna.PlayTo
  10. {
  11. public class TransportCommands
  12. {
  13. private const string CommandBase = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "<SOAP-ENV:Body>" + "<m:{0} xmlns:m=\"{1}\">" + "{2}" + "</m:{0}>" + "</SOAP-ENV:Body></SOAP-ENV:Envelope>";
  14. public List<StateVariable> StateVariables { get; } = new List<StateVariable>();
  15. public List<ServiceAction> ServiceActions { get; } = new List<ServiceAction>();
  16. public static TransportCommands Create(XDocument document)
  17. {
  18. var command = new TransportCommands();
  19. var actionList = document.Descendants(UPnpNamespaces.Svc + "actionList");
  20. foreach (var container in actionList.Descendants(UPnpNamespaces.Svc + "action"))
  21. {
  22. command.ServiceActions.Add(ServiceActionFromXml(container));
  23. }
  24. var stateValues = document.Descendants(UPnpNamespaces.ServiceStateTable).FirstOrDefault();
  25. if (stateValues != null)
  26. {
  27. foreach (var container in stateValues.Elements(UPnpNamespaces.Svc + "stateVariable"))
  28. {
  29. command.StateVariables.Add(FromXml(container));
  30. }
  31. }
  32. return command;
  33. }
  34. private static ServiceAction ServiceActionFromXml(XElement container)
  35. {
  36. var serviceAction = new ServiceAction
  37. {
  38. Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
  39. };
  40. var argumentList = serviceAction.ArgumentList;
  41. foreach (var arg in container.Descendants(UPnpNamespaces.Svc + "argument"))
  42. {
  43. argumentList.Add(ArgumentFromXml(arg));
  44. }
  45. return serviceAction;
  46. }
  47. private static Argument ArgumentFromXml(XElement container)
  48. {
  49. if (container == null)
  50. {
  51. throw new ArgumentNullException(nameof(container));
  52. }
  53. return new Argument
  54. {
  55. Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
  56. Direction = container.GetValue(UPnpNamespaces.Svc + "direction") ?? string.Empty,
  57. RelatedStateVariable = container.GetValue(UPnpNamespaces.Svc + "relatedStateVariable") ?? string.Empty
  58. };
  59. }
  60. private static StateVariable FromXml(XElement container)
  61. {
  62. var allowedValues = Array.Empty<string>();
  63. var element = container.Descendants(UPnpNamespaces.Svc + "allowedValueList")
  64. .FirstOrDefault();
  65. if (element != null)
  66. {
  67. var values = element.Descendants(UPnpNamespaces.Svc + "allowedValue");
  68. allowedValues = values.Select(child => child.Value).ToArray();
  69. }
  70. return new StateVariable
  71. {
  72. Name = container.GetValue(UPnpNamespaces.Svc + "name") ?? string.Empty,
  73. DataType = container.GetValue(UPnpNamespaces.Svc + "dataType") ?? string.Empty,
  74. AllowedValues = allowedValues
  75. };
  76. }
  77. public string BuildPost(ServiceAction action, string xmlNamespace)
  78. {
  79. var stateString = string.Empty;
  80. foreach (var arg in action.ArgumentList)
  81. {
  82. if (string.Equals(arg.Direction, "out", StringComparison.Ordinal))
  83. {
  84. continue;
  85. }
  86. if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal))
  87. {
  88. stateString += BuildArgumentXml(arg, "0");
  89. }
  90. else
  91. {
  92. stateString += BuildArgumentXml(arg, null);
  93. }
  94. }
  95. return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString);
  96. }
  97. public string BuildPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "")
  98. {
  99. var stateString = string.Empty;
  100. foreach (var arg in action.ArgumentList)
  101. {
  102. if (string.Equals(arg.Direction, "out", StringComparison.Ordinal))
  103. {
  104. continue;
  105. }
  106. if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal))
  107. {
  108. stateString += BuildArgumentXml(arg, "0");
  109. }
  110. else
  111. {
  112. stateString += BuildArgumentXml(arg, value.ToString(), commandParameter);
  113. }
  114. }
  115. return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString);
  116. }
  117. public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary<string, string> dictionary)
  118. {
  119. var stateString = string.Empty;
  120. foreach (var arg in action.ArgumentList)
  121. {
  122. if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal))
  123. {
  124. stateString += BuildArgumentXml(arg, "0");
  125. }
  126. else if (dictionary.ContainsKey(arg.Name))
  127. {
  128. stateString += BuildArgumentXml(arg, dictionary[arg.Name]);
  129. }
  130. else
  131. {
  132. stateString += BuildArgumentXml(arg, value.ToString());
  133. }
  134. }
  135. return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString);
  136. }
  137. private string BuildArgumentXml(Argument argument, string? value, string commandParameter = "")
  138. {
  139. var state = StateVariables.FirstOrDefault(a => string.Equals(a.Name, argument.RelatedStateVariable, StringComparison.OrdinalIgnoreCase));
  140. if (state != null)
  141. {
  142. var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
  143. (state.AllowedValues.Count > 0 ? state.AllowedValues[0] : value);
  144. return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
  145. }
  146. return string.Format(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", argument.Name, value);
  147. }
  148. }
  149. }