@ -34,12 +34,12 @@ namespace Emby.Dlna.Didl
{
public class DidlBuilder
{
private readonly CultureInfo _usCulture = new CultureInfo ( "en-US" ) ;
private const string NsDidl = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" ;
private const string NsDc = "http://purl.org/dc/elements/1.1/" ;
private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/" ;
private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/" ;
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" ;
private const string NS_DC = "http://purl.org/dc/elements/1.1/" ;
private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/" ;
private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/" ;
private readonly CultureInfo _usCulture = new CultureInfo ( "en-US" ) ;
private readonly DeviceProfile _profile ;
private readonly IImageProcessor _imageProcessor ;
@ -100,11 +100,11 @@ namespace Emby.Dlna.Didl
{
// writer.WriteStartDocument();
writer . WriteStartElement ( string . Empty , "DIDL-Lite" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "DIDL-Lite" , N sDidl ) ;
writer . WriteAttributeString ( "xmlns" , "dc" , null , N S_DC ) ;
writer . WriteAttributeString ( "xmlns" , "dlna" , null , N S_DLNA ) ;
writer . WriteAttributeString ( "xmlns" , "upnp" , null , N S_UPNP ) ;
writer . WriteAttributeString ( "xmlns" , "dc" , null , N sDc ) ;
writer . WriteAttributeString ( "xmlns" , "dlna" , null , N sDlna ) ;
writer . WriteAttributeString ( "xmlns" , "upnp" , null , N sUpnp ) ;
// didl.SetAttribute("xmlns:sec", NS_SEC);
WriteXmlRootAttributes ( _profile , writer ) ;
@ -147,7 +147,7 @@ namespace Emby.Dlna.Didl
{
var clientId = GetClientId ( item , null ) ;
writer . WriteStartElement ( string . Empty , "item" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "item" , N sDidl ) ;
writer . WriteAttributeString ( "restricted" , "1" ) ;
writer . WriteAttributeString ( "id" , clientId ) ;
@ -207,7 +207,8 @@ namespace Emby.Dlna.Didl
var targetWidth = streamInfo . TargetWidth ;
var targetHeight = streamInfo . TargetHeight ;
var contentFeatureList = new ContentFeatureBuilder ( _profile ) . BuildVideoHeader ( streamInfo . Container ,
var contentFeatureList = new ContentFeatureBuilder ( _profile ) . BuildVideoHeader (
streamInfo . Container ,
streamInfo . TargetVideoCodec . FirstOrDefault ( ) ,
streamInfo . TargetAudioCodec . FirstOrDefault ( ) ,
targetWidth ,
@ -279,7 +280,7 @@ namespace Emby.Dlna.Didl
}
else if ( string . Equals ( subtitleMode , "smi" , StringComparison . OrdinalIgnoreCase ) )
{
writer . WriteStartElement ( string . Empty , "res" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "res" , N sDidl ) ;
writer . WriteAttributeString ( "protocolInfo" , "http-get:*:smi/caption:*" ) ;
@ -288,7 +289,7 @@ namespace Emby.Dlna.Didl
}
else
{
writer . WriteStartElement ( string . Empty , "res" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "res" , N sDidl ) ;
var protocolInfo = string . Format (
CultureInfo . InvariantCulture ,
"http-get:*:text/{0}:*" ,
@ -304,7 +305,7 @@ namespace Emby.Dlna.Didl
private void AddVideoResource ( XmlWriter writer , Filter filter , string contentFeatures , StreamInfo streamInfo )
{
writer . WriteStartElement ( string . Empty , "res" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "res" , N sDidl ) ;
var url = NormalizeDlnaMediaUrl ( streamInfo . ToUrl ( _serverAddress , _accessToken ) ) ;
@ -526,7 +527,7 @@ namespace Emby.Dlna.Didl
private void AddAudioResource ( XmlWriter writer , BaseItem audio , string deviceId , Filter filter , StreamInfo streamInfo = null )
{
writer . WriteStartElement ( string . Empty , "res" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "res" , N sDidl ) ;
if ( streamInfo = = null )
{
@ -583,7 +584,8 @@ namespace Emby.Dlna.Didl
writer . WriteAttributeString ( "bitrate" , targetAudioBitrate . Value . ToString ( _usCulture ) ) ;
}
var mediaProfile = _profile . GetAudioMediaProfile ( streamInfo . Container ,
var mediaProfile = _profile . GetAudioMediaProfile (
streamInfo . Container ,
streamInfo . TargetAudioCodec . FirstOrDefault ( ) ,
targetChannels ,
targetAudioBitrate ,
@ -596,7 +598,8 @@ namespace Emby.Dlna.Didl
? MimeTypes . GetMimeType ( filename )
: mediaProfile . MimeType ;
var contentFeatures = new ContentFeatureBuilder ( _profile ) . BuildAudioHeader ( streamInfo . Container ,
var contentFeatures = new ContentFeatureBuilder ( _profile ) . BuildAudioHeader (
streamInfo . Container ,
streamInfo . TargetAudioCodec . FirstOrDefault ( ) ,
targetAudioBitrate ,
targetSampleRate ,
@ -627,7 +630,7 @@ namespace Emby.Dlna.Didl
public void WriteFolderElement ( XmlWriter writer , BaseItem folder , StubType ? stubType , BaseItem context , int childCount , Filter filter , string requestedId = null )
{
writer . WriteStartElement ( string . Empty , "container" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "container" , N sDidl ) ;
writer . WriteAttributeString ( "restricted" , "1" ) ;
writer . WriteAttributeString ( "searchable" , "1" ) ;
@ -714,7 +717,7 @@ namespace Emby.Dlna.Didl
// MediaMonkey for example won't display content without a title
// if (filter.Contains("dc:title"))
{
AddValue ( writer , "dc" , "title" , GetDisplayName ( item , itemStubType , context ) , N S_DC ) ;
AddValue ( writer , "dc" , "title" , GetDisplayName ( item , itemStubType , context ) , N sDc ) ;
}
WriteObjectClass ( writer , item , itemStubType ) ;
@ -723,7 +726,7 @@ namespace Emby.Dlna.Didl
{
if ( item . PremiereDate . HasValue )
{
AddValue ( writer , "dc" , "date" , item . PremiereDate . Value . ToString ( "o" , CultureInfo . InvariantCulture ) , N S_DC ) ;
AddValue ( writer , "dc" , "date" , item . PremiereDate . Value . ToString ( "o" , CultureInfo . InvariantCulture ) , N sDc ) ;
}
}
@ -731,13 +734,13 @@ namespace Emby.Dlna.Didl
{
foreach ( var genre in item . Genres )
{
AddValue ( writer , "upnp" , "genre" , genre , N S_UPNP ) ;
AddValue ( writer , "upnp" , "genre" , genre , N sUpnp ) ;
}
}
foreach ( var studio in item . Studios )
{
AddValue ( writer , "upnp" , "publisher" , studio , N S_UPNP ) ;
AddValue ( writer , "upnp" , "publisher" , studio , N sUpnp ) ;
}
if ( ! ( item is Folder ) )
@ -748,28 +751,29 @@ namespace Emby.Dlna.Didl
if ( ! string . IsNullOrWhiteSpace ( desc ) )
{
AddValue ( writer , "dc" , "description" , desc , N S_DC ) ;
AddValue ( writer , "dc" , "description" , desc , N sDc ) ;
}
}
// if (filter.Contains("upnp:longDescription"))
// {
// {
// if (!string.IsNullOrWhiteSpace(item.Overview))
// {
// AddValue(writer, "upnp", "longDescription", item.Overview, N S_UPNP );
// AddValue(writer, "upnp", "longDescription", item.Overview, N sUpnp );
// }
// }
// }
}
if ( ! string . IsNullOrEmpty ( item . OfficialRating ) )
{
if ( filter . Contains ( "dc:rating" ) )
{
AddValue ( writer , "dc" , "rating" , item . OfficialRating , N S_DC ) ;
AddValue ( writer , "dc" , "rating" , item . OfficialRating , N sDc ) ;
}
if ( filter . Contains ( "upnp:rating" ) )
{
AddValue ( writer , "upnp" , "rating" , item . OfficialRating , N S_UPNP ) ;
AddValue ( writer , "upnp" , "rating" , item . OfficialRating , N sUpnp ) ;
}
}
@ -781,7 +785,7 @@ namespace Emby.Dlna.Didl
// More types here
// http://oss.linn.co.uk/repos/Public/LibUpnpCil/DidlLite/UpnpAv/Test/TestDidlLite.cs
writer . WriteStartElement ( "upnp" , "class" , N S_UPNP ) ;
writer . WriteStartElement ( "upnp" , "class" , N sUpnp ) ;
if ( item . IsDisplayedAsFolder | | stubType . HasValue )
{
@ -882,7 +886,7 @@ namespace Emby.Dlna.Didl
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 , N S_UPNP ) ;
AddValue ( writer , "upnp" , type . ToLowerInvariant ( ) , actor . Name , N sUpnp ) ;
}
}
@ -896,8 +900,8 @@ namespace Emby.Dlna.Didl
{
foreach ( var artist in hasArtists . Artists )
{
AddValue ( writer , "upnp" , "artist" , artist , N S_UPNP ) ;
AddValue ( writer , "dc" , "creator" , artist , N S_DC ) ;
AddValue ( writer , "upnp" , "artist" , artist , N sUpnp ) ;
AddValue ( writer , "dc" , "creator" , artist , N sDc ) ;
// If it doesn't support album artists (musicvideo), then tag as both
if ( hasAlbumArtists = = null )
@ -917,16 +921,16 @@ namespace Emby.Dlna.Didl
if ( ! string . IsNullOrWhiteSpace ( item . Album ) )
{
AddValue ( writer , "upnp" , "album" , item . Album , N S_UPNP ) ;
AddValue ( writer , "upnp" , "album" , item . Album , N sUpnp ) ;
}
if ( item . IndexNumber . HasValue )
{
AddValue ( writer , "upnp" , "originalTrackNumber" , item . IndexNumber . Value . ToString ( _usCulture ) , N S_UPNP ) ;
AddValue ( writer , "upnp" , "originalTrackNumber" , item . IndexNumber . Value . ToString ( _usCulture ) , N sUpnp ) ;
if ( item is Episode )
{
AddValue ( writer , "upnp" , "episodeNumber" , item . IndexNumber . Value . ToString ( _usCulture ) , N S_UPNP ) ;
AddValue ( writer , "upnp" , "episodeNumber" , item . IndexNumber . Value . ToString ( _usCulture ) , N sUpnp ) ;
}
}
}
@ -935,7 +939,7 @@ namespace Emby.Dlna.Didl
{
try
{
writer . WriteStartElement ( "upnp" , "artist" , N S_UPNP ) ;
writer . WriteStartElement ( "upnp" , "artist" , N sUpnp ) ;
writer . WriteAttributeString ( "role" , "AlbumArtist" ) ;
writer . WriteString ( name ) ;
@ -971,14 +975,14 @@ namespace Emby.Dlna.Didl
var albumartUrlInfo = GetImageUrl ( imageInfo , _profile . MaxAlbumArtWidth , _profile . MaxAlbumArtHeight , "jpg" ) ;
writer . WriteStartElement ( "upnp" , "albumArtURI" , N S_UPNP ) ;
writer . WriteAttributeString ( "dlna" , "profileID" , N S_DLNA , _profile . AlbumArtPn ) ;
writer . WriteStartElement ( "upnp" , "albumArtURI" , N sUpnp ) ;
writer . WriteAttributeString ( "dlna" , "profileID" , N sDlna , _profile . AlbumArtPn ) ;
writer . WriteString ( albumartUrlInfo . Url ) ;
writer . WriteFullEndElement ( ) ;
// TOOD: Remove these default values
var iconUrlInfo = GetImageUrl ( imageInfo , _profile . MaxIconWidth ? ? 48 , _profile . MaxIconHeight ? ? 48 , "jpg" ) ;
writer . WriteElementString ( "upnp" , "icon" , N S_UPNP , iconUrlInfo . Url ) ;
writer . WriteElementString ( "upnp" , "icon" , N sUpnp , iconUrlInfo . Url ) ;
if ( ! _profile . EnableAlbumArtInDidl )
{
@ -1021,7 +1025,7 @@ namespace Emby.Dlna.Didl
var albumartUrlInfo = GetImageUrl ( imageInfo , maxWidth , maxHeight , format ) ;
writer . WriteStartElement ( string . Empty , "res" , N S_DIDL ) ;
writer . WriteStartElement ( string . Empty , "res" , N sDidl ) ;
// 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
@ -1150,16 +1154,16 @@ namespace Emby.Dlna.Didl
}
// try
// {
// {
// var size = _imageProcessor.GetImageSize(imageInfo);
// width = size.Width;
// height = size.Height;
// }
// }
// catch
// {
// {
// }
// }
var inputFormat = ( Path . GetExtension ( imageInfo . Path ) ? ? string . Empty )
. TrimStart ( '.' )