|
@@ -45,6 +45,7 @@ namespace Emby.Dlna.Didl
|
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
|
|
private readonly ILogger _logger;
|
|
|
private readonly IMediaEncoder _mediaEncoder;
|
|
|
+ private readonly ILibraryManager _libraryManager;
|
|
|
|
|
|
public DidlBuilder(
|
|
|
DeviceProfile profile,
|
|
@@ -56,7 +57,8 @@ namespace Emby.Dlna.Didl
|
|
|
ILocalizationManager localization,
|
|
|
IMediaSourceManager mediaSourceManager,
|
|
|
ILogger logger,
|
|
|
- IMediaEncoder mediaEncoder)
|
|
|
+ IMediaEncoder mediaEncoder,
|
|
|
+ ILibraryManager libraryManager)
|
|
|
{
|
|
|
_profile = profile;
|
|
|
_user = user;
|
|
@@ -68,6 +70,7 @@ namespace Emby.Dlna.Didl
|
|
|
_mediaSourceManager = mediaSourceManager;
|
|
|
_logger = logger;
|
|
|
_mediaEncoder = mediaEncoder;
|
|
|
+ _libraryManager = libraryManager;
|
|
|
}
|
|
|
|
|
|
public static string NormalizeDlnaMediaUrl(string url)
|
|
@@ -75,7 +78,7 @@ namespace Emby.Dlna.Didl
|
|
|
return url + "&dlnaheaders=true";
|
|
|
}
|
|
|
|
|
|
- public string GetItemDidl(DlnaOptions options, BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo)
|
|
|
+ public string GetItemDidl(BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo)
|
|
|
{
|
|
|
var settings = new XmlWriterSettings
|
|
|
{
|
|
@@ -100,7 +103,7 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
WriteXmlRootAttributes(_profile, writer);
|
|
|
|
|
|
- WriteItemElement(options, writer, item, user, context, null, deviceId, filter, streamInfo);
|
|
|
+ WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo);
|
|
|
|
|
|
writer.WriteFullEndElement();
|
|
|
//writer.WriteEndDocument();
|
|
@@ -127,7 +130,6 @@ namespace Emby.Dlna.Didl
|
|
|
}
|
|
|
|
|
|
public void WriteItemElement(
|
|
|
- DlnaOptions options,
|
|
|
XmlWriter writer,
|
|
|
BaseItem item,
|
|
|
User user,
|
|
@@ -164,25 +166,23 @@ namespace Emby.Dlna.Didl
|
|
|
// refID?
|
|
|
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
|
|
|
|
|
|
- var hasMediaSources = item as IHasMediaSources;
|
|
|
-
|
|
|
- if (hasMediaSources != null)
|
|
|
+ if (item is IHasMediaSources)
|
|
|
{
|
|
|
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
- AddAudioResource(options, writer, item, deviceId, filter, streamInfo);
|
|
|
+ AddAudioResource(writer, item, deviceId, filter, streamInfo);
|
|
|
}
|
|
|
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
- AddVideoResource(options, writer, item, deviceId, filter, streamInfo);
|
|
|
+ AddVideoResource(writer, item, deviceId, filter, streamInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- AddCover(item, context, null, writer);
|
|
|
+ AddCover(item, null, writer);
|
|
|
writer.WriteFullEndElement();
|
|
|
}
|
|
|
|
|
|
- private void AddVideoResource(DlnaOptions options, XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
|
|
+ private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
|
|
{
|
|
|
if (streamInfo == null)
|
|
|
{
|
|
@@ -226,7 +226,7 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
foreach (var contentFeature in contentFeatureList)
|
|
|
{
|
|
|
- AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo);
|
|
|
+ AddVideoResource(writer, filter, contentFeature, streamInfo);
|
|
|
}
|
|
|
|
|
|
var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken);
|
|
@@ -283,7 +283,10 @@ namespace Emby.Dlna.Didl
|
|
|
else
|
|
|
{
|
|
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
|
|
- var protocolInfo = string.Format("http-get:*:text/{0}:*", info.Format.ToLowerInvariant());
|
|
|
+ var protocolInfo = string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "http-get:*:text/{0}:*",
|
|
|
+ info.Format.ToLowerInvariant());
|
|
|
writer.WriteAttributeString("protocolInfo", protocolInfo);
|
|
|
|
|
|
writer.WriteString(info.Url);
|
|
@@ -293,7 +296,7 @@ namespace Emby.Dlna.Didl
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
|
|
+ private void AddVideoResource(XmlWriter writer, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
|
|
{
|
|
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
|
|
|
|
@@ -335,7 +338,13 @@ namespace Emby.Dlna.Didl
|
|
|
{
|
|
|
if (targetWidth.HasValue && targetHeight.HasValue)
|
|
|
{
|
|
|
- writer.WriteAttributeString("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value));
|
|
|
+ writer.WriteAttributeString(
|
|
|
+ "resolution",
|
|
|
+ string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "{0}x{1}",
|
|
|
+ targetWidth.Value,
|
|
|
+ targetHeight.Value));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -369,17 +378,19 @@ namespace Emby.Dlna.Didl
|
|
|
streamInfo.TargetVideoCodecTag,
|
|
|
streamInfo.IsTargetAVC);
|
|
|
|
|
|
- var filename = url.Substring(0, url.IndexOf('?'));
|
|
|
+ var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
|
|
|
|
|
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
|
|
? MimeTypes.GetMimeType(filename)
|
|
|
: mediaProfile.MimeType;
|
|
|
|
|
|
- writer.WriteAttributeString("protocolInfo", string.Format(
|
|
|
- "http-get:*:{0}:{1}",
|
|
|
- mimeType,
|
|
|
- contentFeatures
|
|
|
- ));
|
|
|
+ writer.WriteAttributeString(
|
|
|
+ "protocolInfo",
|
|
|
+ string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "http-get:*:{0}:{1}",
|
|
|
+ mimeType,
|
|
|
+ contentFeatures));
|
|
|
|
|
|
writer.WriteString(url);
|
|
|
|
|
@@ -420,7 +431,10 @@ namespace Emby.Dlna.Didl
|
|
|
if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value == 0
|
|
|
&& season.IndexNumber.HasValue && season.IndexNumber.Value != 0)
|
|
|
{
|
|
|
- return string.Format(_localization.GetLocalizedString("ValueSpecialEpisodeName"), item.Name);
|
|
|
+ return string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ _localization.GetLocalizedString("ValueSpecialEpisodeName"),
|
|
|
+ item.Name);
|
|
|
}
|
|
|
|
|
|
if (item.IndexNumber.HasValue)
|
|
@@ -439,7 +453,7 @@ namespace Emby.Dlna.Didl
|
|
|
return item.Name;
|
|
|
}
|
|
|
|
|
|
- private void AddAudioResource(DlnaOptions options, XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
|
|
+ private void AddAudioResource(XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
|
|
{
|
|
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
|
|
|
|
@@ -505,7 +519,7 @@ namespace Emby.Dlna.Didl
|
|
|
targetSampleRate,
|
|
|
targetAudioBitDepth);
|
|
|
|
|
|
- var filename = url.Substring(0, url.IndexOf('?'));
|
|
|
+ var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
|
|
|
|
|
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
|
|
? MimeTypes.GetMimeType(filename)
|
|
@@ -521,11 +535,13 @@ namespace Emby.Dlna.Didl
|
|
|
streamInfo.RunTimeTicks ?? 0,
|
|
|
streamInfo.TranscodeSeekInfo);
|
|
|
|
|
|
- writer.WriteAttributeString("protocolInfo", string.Format(
|
|
|
- "http-get:*:{0}:{1}",
|
|
|
- mimeType,
|
|
|
- contentFeatures
|
|
|
- ));
|
|
|
+ writer.WriteAttributeString(
|
|
|
+ "protocolInfo",
|
|
|
+ string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "http-get:*:{0}:{1}",
|
|
|
+ mimeType,
|
|
|
+ contentFeatures));
|
|
|
|
|
|
writer.WriteString(url);
|
|
|
|
|
@@ -548,7 +564,7 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
var clientId = GetClientId(folder, stubType);
|
|
|
|
|
|
- if (string.Equals(requestedId, "0"))
|
|
|
+ if (string.Equals(requestedId, "0", StringComparison.Ordinal))
|
|
|
{
|
|
|
writer.WriteAttributeString("id", "0");
|
|
|
writer.WriteAttributeString("parentID", "-1");
|
|
@@ -577,7 +593,7 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
AddGeneralProperties(folder, stubType, context, writer, filter);
|
|
|
|
|
|
- AddCover(folder, context, stubType, writer);
|
|
|
+ AddCover(folder, stubType, writer);
|
|
|
|
|
|
writer.WriteFullEndElement();
|
|
|
}
|
|
@@ -610,7 +626,10 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
if (playbackPositionTicks > 0)
|
|
|
{
|
|
|
- var elementValue = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds).ToString(_usCulture));
|
|
|
+ var elementValue = string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "BM={0}",
|
|
|
+ Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds));
|
|
|
AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value);
|
|
|
}
|
|
|
}
|
|
@@ -763,37 +782,37 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
private void AddPeople(BaseItem item, XmlWriter writer)
|
|
|
{
|
|
|
- //var types = new[]
|
|
|
- //{
|
|
|
- // PersonType.Director,
|
|
|
- // PersonType.Writer,
|
|
|
- // PersonType.Producer,
|
|
|
- // PersonType.Composer,
|
|
|
- // "Creator"
|
|
|
- //};
|
|
|
+ var types = new[]
|
|
|
+ {
|
|
|
+ PersonType.Director,
|
|
|
+ PersonType.Writer,
|
|
|
+ PersonType.Producer,
|
|
|
+ PersonType.Composer,
|
|
|
+ "Creator"
|
|
|
+ };
|
|
|
|
|
|
- //var people = _libraryManager.GetPeople(item);
|
|
|
+ var people = _libraryManager.GetPeople(item);
|
|
|
|
|
|
- //var index = 0;
|
|
|
+ var index = 0;
|
|
|
|
|
|
- //// Seeing some LG models locking up due content with large lists of people
|
|
|
- //// The actual issue might just be due to processing a more metadata than it can handle
|
|
|
- //var limit = 6;
|
|
|
+ // Seeing some LG models locking up due content with large lists of people
|
|
|
+ // The actual issue might just be due to processing a more metadata than it can handle
|
|
|
+ var limit = 6;
|
|
|
|
|
|
- //foreach (var actor in people)
|
|
|
- //{
|
|
|
- // var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
|
|
|
- // ?? PersonType.Actor;
|
|
|
+ foreach (var actor in people)
|
|
|
+ {
|
|
|
+ var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
|
|
|
+ ?? PersonType.Actor;
|
|
|
|
|
|
- // AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
|
|
|
+ AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
|
|
|
|
|
|
- // index++;
|
|
|
+ index++;
|
|
|
|
|
|
- // if (index >= limit)
|
|
|
- // {
|
|
|
- // break;
|
|
|
- // }
|
|
|
- //}
|
|
|
+ if (index >= limit)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
|
|
@@ -870,7 +889,7 @@ namespace Emby.Dlna.Didl
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer)
|
|
|
+ private void AddCover(BaseItem item, StubType? stubType, XmlWriter writer)
|
|
|
{
|
|
|
ImageDownloadInfo imageInfo = GetImageInfo(item);
|
|
|
|
|
@@ -915,17 +934,8 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
}
|
|
|
|
|
|
- private void AddEmbeddedImageAsCover(string name, XmlWriter writer)
|
|
|
- {
|
|
|
- writer.WriteStartElement("upnp", "albumArtURI", NS_UPNP);
|
|
|
- writer.WriteAttributeString("dlna", "profileID", NS_DLNA, _profile.AlbumArtPn);
|
|
|
- writer.WriteString(_serverAddress + "/Dlna/icons/people480.jpg");
|
|
|
- writer.WriteFullEndElement();
|
|
|
-
|
|
|
- writer.WriteElementString("upnp", "icon", NS_UPNP, _serverAddress + "/Dlna/icons/people48.jpg");
|
|
|
- }
|
|
|
-
|
|
|
- private void AddImageResElement(BaseItem item,
|
|
|
+ private void AddImageResElement(
|
|
|
+ BaseItem item,
|
|
|
XmlWriter writer,
|
|
|
int maxWidth,
|
|
|
int maxHeight,
|
|
@@ -951,13 +961,17 @@ namespace Emby.Dlna.Didl
|
|
|
var contentFeatures = new ContentFeatureBuilder(_profile)
|
|
|
.BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
|
|
|
|
|
|
- writer.WriteAttributeString("protocolInfo", string.Format(
|
|
|
- "http-get:*:{0}:{1}",
|
|
|
- MimeTypes.GetMimeType("file." + format),
|
|
|
- contentFeatures
|
|
|
- ));
|
|
|
+ writer.WriteAttributeString(
|
|
|
+ "protocolInfo",
|
|
|
+ string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "http-get:*:{0}:{1}",
|
|
|
+ MimeTypes.GetMimeType("file." + format),
|
|
|
+ contentFeatures));
|
|
|
|
|
|
- writer.WriteAttributeString("resolution", string.Format("{0}x{1}", width, height));
|
|
|
+ writer.WriteAttributeString(
|
|
|
+ "resolution",
|
|
|
+ string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
|
|
|
|
|
|
writer.WriteString(albumartUrlInfo.Url);
|
|
|
|
|
@@ -1096,7 +1110,9 @@ namespace Emby.Dlna.Didl
|
|
|
|
|
|
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
|
|
|
{
|
|
|
- var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
|
|
|
+ var url = string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ "{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
|
|
|
_serverAddress,
|
|
|
info.ItemId.ToString("N", CultureInfo.InvariantCulture),
|
|
|
info.Type,
|