Difference between revisions of "Developer:Media Server Extensions"
(→Index maps) |
|||
(113 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | = | + | = Introduction = |
− | The ContentDirectory service | + | The ContentDirectory service has various limitations which become apparent when implementing control points on different hardware platforms. This document aims to outline some ideas that address the various shortcomings of the ContentDirectory specification. |
− | == | + | == Container map == |
− | The current specification | + | The current ContentDirectory specification makes it tricky for a control point to display the returned contents in an appropriate, aesthetically pleasing, manner for the content being viewed. This is because the ContentDirectory specification does not allow for a control point to know in advanced what content to expect when browsing through any particular hierarchy. |
− | + | An example of this might be, at a particular point in the browse hierarchy the ContentDirectory will return a list of albums which in turn will contain a list of tracks. A UI might wish to represent this list of albums as a grid and the album's tracks as a header and a list of the tracks. Currently it is not possible for the UI to know when it gets to a point in a hierarchy where the hierarchy represents a list of albums followed by a list of tracks. | |
− | + | The container map extension allows a media server to express its container hierarchy in advance of the control point navigating it. This is done using an OpenHome vendor extension to the device XML. | |
− | + | Three types of mapped container are defined: browse, link, and search. | |
− | + | The browse map defines named top level containers that represent significant starting points for browsing that can meaningfully be presented in top level tabs of a control point UI. The browse map is expressed within the X_MAP_BROWSE element of X_MAP. | |
− | + | The link map defines containers that can be meaningfully linked to from track or album details. For instance a track will typically have an artist defined. If an entry for "artist" is defined in the link map then it will be possible for the user of a control point to quickly access this artist-related container by clicking on the track's artist text. Similar links might be offered for "genre", "composer", "conductor", etc. The link map is expressed within the X_MAP_LINK element of X_MAP. | |
− | + | The search map defines the different kinds of search containers and the type of results that they produce. The search map is expressed within the X_MAP_SEARCH element of X_MAP. | |
− | == | + | === Browse map === |
− | + | The X_MAP_BROWSE element must contain 1 or more X_MAP_BROWSE_ENTRY elements. | |
− | + | The X_MAP_BROWSE_ENTRY has three child elements. | |
− | + | X_MAP_BROWSE_ENTRY_NAME is a string that can be used by a control point to label a tab containing this browse hierarchy. | |
+ | |||
+ | X_MAP_BROWSE_ENTRY_ID is the UPnP container id that contains the root of this browse hierarchy. This id is then submitted to the ContentDirectory service using the Browse action as usual. The returned contents are navigated using subsequent Browse request as usual. The difference is that the control point knows in advance what kind of results to expect at each level. | ||
+ | |||
+ | X_MAP_BROWSE_ENTRY_TYPE is a space separated list of strings that maps out the kind of containers that are to be found at each level of this browse hierarchy. For instance, "artist album" represents a browse hierarchy giving a container containing only artist containers, each of which contains only album containers, each of which contains only tracks. | ||
+ | |||
+ | There should be an X_MAP_BROWSE_ENTRY for each root browse hierarchy defined by the media server. | ||
+ | |||
+ | For example: | ||
+ | |||
+ | <X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY_NAME>Genre</X_MAP_BROWSE_ENTRY_NAME> | ||
+ | <X_MAP_BROWSE_ENTRY_ID>db/browse/genre</X_MAP_BROWSE_ENTRY_ID> | ||
+ | <X_MAP_BROWSE_ENTRY_TYPE>genre artist album</X_MAP_BROWSE_ENTRY_TYPE> | ||
+ | </X_MAP_BROWSE_ENTRY> | ||
+ | |||
+ | === Link map === | ||
+ | |||
+ | The X_MAP_LINK element must contain 1 or more X_MAP_LINK_ENTRY elements. | ||
+ | |||
+ | The X_MAP_LINK_ENTRY has three child elements. | ||
+ | |||
+ | X_MAP_LINK_ENTRY_TAG is a string that defines which type of metadata is the target for this link. e.g. "artist", "genre", "composer", etc. See the type section below. | ||
+ | |||
+ | X_MAP_LINK_ENTRY_ID_PREFIX is a string that is prefix for a UPnP container id. The link can be taken by browsing to the container whose id is the result of appending the associated metadata value to this prefix. For instance, if the prefix for an "artist" link is defined as db/link/artist/, and a track returned anywhere in the media server's library has "Pink Floyd" as its artist. Then the linked container will have an id of db/link/artist/Pink Floyd. | ||
+ | |||
+ | X_MAP_LINK_ENTRY_TYPE represents the type of browse hierarchy returned when taking this type of link. See X_MAP_BROWSE_ENTRY_TYPE for details. | ||
+ | |||
+ | There should be an X_MAP_LINK_ENTRY for each piece of metadata that the media server allows to be linked. | ||
+ | |||
+ | For example: | ||
+ | |||
+ | <X_MAP_LINK_ENTRY> | ||
+ | <X_MAP_LINK_ENTRY_TAG>artist</X_MAP_LINK_ENTRY_TAG> | ||
+ | <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/artist/</X_MAP_LINK_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> | ||
+ | </X_MAP_LINK_ENTRY> | ||
+ | |||
+ | The example above defines a browse hierarchy that is created when linking from an artist name. The hierarchy created provides a list of linked artist albums which in turn provide a list of tracks. | ||
+ | |||
+ | === Search map === | ||
+ | |||
+ | The X_MAP_SEARCH element must contain 1 or more X_MAP_SEARCH_ENTRY elements. | ||
+ | |||
+ | The X_MAP_SEARCH_ENTRY has three child elements. | ||
+ | |||
+ | X_MAP_SEARCH_ENTRY_NAME is a string that can be used by a control point to label a tab containing these search results. | ||
+ | |||
+ | X_MAP_SEARCH_ENTRY_ID_PREFIX is a string that is a prefix for a UPnP container id. The search results can be found by browsing to the container whose id is the result of appending the search string to this prefix. For instance, if the prefix for an "album" search is defined as db/search/album/, and the search string is "blue", then the search results container will have an id of db/search/album/blue. | ||
+ | |||
+ | X_MAP_SEARCH_ENTRY_TYPE represents the type of browse hierarchy returned when taking this type of search. See X_MAP_BROWSE_ENTRY_TYPE for details. | ||
+ | |||
+ | There should be an X_MAP_SEARCH_ENTRY for each type of search offered by the media server. | ||
+ | |||
+ | For example: | ||
+ | |||
+ | <X_MAP_SEARCH_ENTRY> | ||
+ | <X_MAP_SEARCH_ENTRY_NAME>Artist</X_MAP_SEARCH_ENTRY_NAME> | ||
+ | <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/artist/</X_MAP_SEARCH_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_SEARCH_ENTRY_TYPE>artist album</X_MAP_SEARCH_ENTRY_TYPE> | ||
+ | </X_MAP_SEARCH_ENTRY> | ||
+ | |||
+ | The example above defines a browse hierarchy that is created when searching for an artist. The hierarchy created provides a list of artists, which in turn provide a list of albums, which in turn provide a list of tracks. | ||
+ | |||
+ | === Types === | ||
+ | |||
+ | The list of allowed types for X_BROWSE_ENTRY_TYPE, X_MAP_LINK_ENTRY_TAG, X_LINK_ENTRY_TYPE, and X_SEARCH_ENTRY_TYPE | ||
+ | |||
+ | genre | ||
+ | artist | ||
+ | composer | ||
+ | conductor | ||
+ | album | ||
+ | year | ||
+ | mixed | ||
+ | |||
+ | mixed is a special value that represents a container that has mixed entries. It is not a valid type for the X_MAP_LINK_ENTRY_TAG element. | ||
+ | |||
+ | === Example device XML === | ||
+ | |||
+ | <root xmlns="urn:schemas-upnp-org:device-1-0"> | ||
+ | <specVersion> | ||
+ | <major>1</major> | ||
+ | <minor>1</minor> | ||
+ | </specVersion> | ||
+ | <device> | ||
+ | <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType> | ||
+ | <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMS-1.50</dlna:X_DLNADOC> | ||
+ | <dlna:X_DLNACAP xmlns:dlna="urn:schemas-dlna-org:device-1-0">av-upload,image-upload,audio-upload</dlna:X_DLNACAP> | ||
+ | <openhome:X_MAP xmlns:openhome="http://www.openhome.org"> | ||
+ | <X_MAP_BROWSE> | ||
+ | <X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY_NAME>Albums</X_MAP_BROWSE_ENTRY_NAME> | ||
+ | <X_MAP_BROWSE_ENTRY_ID>db/browse/albums</X_MAP_BROWSE_ENTRY_ID> | ||
+ | <X_MAP_BROWSE_ENTRY_TYPE>album</X_MAP_BROWSE_ENTRY_TYPE> | ||
+ | </X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY_NAME>Artists</X_MAP_BROWSE_ENTRY_NAME> | ||
+ | <X_MAP_BROWSE_ENTRY_ID>db/browse/artists</X_MAP_BROWSE_ENTRY_ID> | ||
+ | <X_MAP_BROWSE_ENTRY_TYPE>artist album</X_MAP_BROWSE_ENTRY_TYPE> | ||
+ | </X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY> | ||
+ | <X_MAP_BROWSE_ENTRY_NAME>Folders</X_MAP_BROWSE_ENTRY_NAME> | ||
+ | <X_MAP_BROWSE_ENTRY_ID>db/browse/folders</X_MAP_BROWSE_ENTRY_ID> | ||
+ | <X_MAP_BROWSE_ENTRY_TYPE>mixed</X_MAP_BROWSE_ENTRY_TYPE> | ||
+ | </X_MAP_BROWSE_ENTRY> | ||
+ | </X_MAP_BROWSE> | ||
+ | <X_MAP_LINK> | ||
+ | <X_MAP_LINK_ENTRY> | ||
+ | <X_MAP_LINK_ENTRY_TAG>artist</X_MAP_LINK_ENTRY_TAG> | ||
+ | <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/artist/</X_MAP_LINK_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> | ||
+ | </X_MAP_LINK_ENTRY> | ||
+ | <X_MAP_LINK_ENTRY> | ||
+ | <X_MAP_LINK_ENTRY_TAG>composer</X_MAP_LINK_ENTRY_TAG> | ||
+ | <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/composer/</X_MAP_LINK_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> | ||
+ | </X_MAP_LINK_ENTRY> | ||
+ | </X_MAP_LINK> | ||
+ | <X_MAP_SEARCH> | ||
+ | <X_MAP_SEARCH_ENTRY> | ||
+ | <X_MAP_SEARCH_ENTRY_NAME>Artist</X_MAP_SEARCH_ENTRY_NAME> | ||
+ | <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/artist/</X_MAP_SEARCH_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_SEARCH_ENTRY_TYPE>artist album</X_MAP_SEARCH_ENTRY_TYPE> | ||
+ | </X_MAP_SEARCH_ENTRY> | ||
+ | <X_MAP_SEARCH_ENTRY> | ||
+ | <X_MAP_SEARCH_ENTRY_NAME>Tracks</X_MAP_SEARCH_ENTRY_NAME> | ||
+ | <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/all/</X_MAP_SEARCH_ENTRY_ID_PREFIX> | ||
+ | <X_MAP_SEARCH_ENTRY_TYPE></X_MAP_SEARCH_ENTRY_TYPE> | ||
+ | </X_MAP_SEARCH_ENTRY> | ||
+ | </X_MAP_SEARCH> | ||
+ | </openhome:X_MAP> | ||
+ | <presentationURL>http://10.2.1.170:4000/res/linn.co.uk.kazooserver/index.html</presentationURL> | ||
+ | <friendlyName>Linn Kazoo Server [R&D Mac Mini]</friendlyName> | ||
+ | <manufacturer>Linn</manufacturer> | ||
+ | <manufacturerURL>http://www.linn.co.uk</manufacturerURL> | ||
+ | <modelName>Kazoo Server</modelName> | ||
+ | <modelURL>http://oss.linn.co.uk/trac/wiki/KazooServer</modelURL> | ||
+ | <UDN>uuid:ac3d630e37b5f11ff5cdd23c0f5a7400</UDN> | ||
+ | <iconList> | ||
+ | <icon> | ||
+ | <mimetype>image/png</mimetype> | ||
+ | <width>65</width> | ||
+ | <height>65</height> | ||
+ | <depth>32</depth> | ||
+ | <url>ac3d630e37b5f11ff5cdd23c0f5a7400/resource/icon/icon</url> | ||
+ | </icon> | ||
+ | </iconList> | ||
+ | <serviceList> | ||
+ | <service> | ||
+ | <serviceType>urn:av-openhome-org:service:PlaylistManager:1</serviceType> | ||
+ | <serviceId>urn:av-openhome-org:serviceId:PlaylistManager</serviceId> | ||
+ | <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/av.openhome.org-PlaylistManager-1/service.xml</SCPDURL> | ||
+ | <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/av.openhome.org-PlaylistManager-1/control</controlURL> | ||
+ | <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/av.openhome.org-PlaylistManager-1/event</eventSubURL> | ||
+ | </service> | ||
+ | <service> | ||
+ | <serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType> | ||
+ | <serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId> | ||
+ | <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/upnp.org-ContentDirectory-1/service.xml</SCPDURL> | ||
+ | <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ContentDirectory-1/control</controlURL> | ||
+ | <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ContentDirectory-1/event</eventSubURL> | ||
+ | </service> | ||
+ | <service> | ||
+ | <serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType> | ||
+ | <serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId> | ||
+ | <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/upnp.org-ConnectionManager-1/service.xml</SCPDURL> | ||
+ | <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ConnectionManager-1/control</controlURL> | ||
+ | <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ConnectionManager-1/event</eventSubURL> | ||
+ | </service> | ||
+ | </serviceList> | ||
+ | </device> | ||
+ | </root> | ||
+ | |||
+ | == Index maps == | ||
+ | |||
+ | Large lists are difficult to navigate, especially on mobile devices. Mobile devices added the idea of an index map to improve this situation. The index map allows a users to jump to different sections in a large list, similar to what is possible with a scrollbar on desktops. | ||
+ | |||
+ | In order for a control point to generate an index map for any particular level in a ContentDirectory's hierarchy it first needs to download all the objects in the container, figure out if they are sorted and then calculate the index map. This means that a user will need to wait, perhaps minutes, before an index map is able to be presented on the UI. | ||
+ | |||
+ | The media server can optionally return an index map for container that are in alphabetical order. This implemented through a OpenHome vendor extension of the DIDL-Lite XML. Below shows an example DIDL-Lite with an index map included. | ||
+ | |||
+ | <DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"> | ||
+ | <container id="db/ba37a2ac24efa676c8676aab71a6cdf074" parentID="0" restricted="true"> | ||
+ | <dc:title xmlns:dc="http://purl.org/dc/elements/1.1/">Worlds Apart [Deluxe Edition]</dc:title> | ||
+ | <upnp:udn xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">ac3d630e37b5f11ff5cdd23c0f5a7400</upnp:udn> | ||
+ | <upnp:class xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">object.container.album.musicAlbum</upnp:class> | ||
+ | <upnp:artist xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">...And You Will Know Us by the Trail of Dead</upnp:artist> | ||
+ | <upnp:albumArtURI>http://10.2.1.170:4000/linn.co.uk.kazooserver/ms/artwork/37a2ac2?size=0</upnp:albumArtURI> | ||
+ | </container> | ||
+ | <desc nameSpace="openhome.org"> | ||
+ | <openhome.org:indexmap>0 10 10 10 10 10 0 0 0 0 10 12 1 10 10 10 12 17 18 1 0 20 0 20 20 2 2 24</indexmap> | ||
+ | </desc> | ||
+ | </DIDL-Lite> | ||
+ | |||
+ | The index map contains a space separated list of 28 number representing the total number of items that begin with that letter. #, represents everything below A, largely digits and punctuation and + represents everything above Z, largely international characters not collatable within the roman alphabet. | ||
+ | |||
+ | # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + | ||
+ | |||
+ | == Image Resolution == | ||
+ | |||
+ | Control points running on different platforms have different memory limits and display technologies. This means that a control point on a PC might want to display artwork at a high resolution, while a control point on a PDA might want to display artwork at a much lower resolution. | ||
+ | |||
+ | Media servers often try to solve this problem using one of the following two methods: | ||
# A configurable parameter that scales all artwork to a user defined size | # A configurable parameter that scales all artwork to a user defined size | ||
− | # A profile system where a user can create profiles for each class of control point they have and configure a parameter that scales all artwork to a user defined size per profile< | + | # A profile system where a user can create profiles for each class of control point they have and configure a parameter that scales all artwork to a user defined size per profile |
+ | |||
+ | The first solution is highly problematic because it limits the resolution of artwork across the whole network. But a single network very often contains control points that can display high resolution images AND control points that can't. | ||
+ | |||
+ | The second solution is just architecturally poor, turning the relationship between a control point and a media server on its head. Why should the media server try to infer what a control point needs through configuration when the control point is perfectly capable of telling the media server its exact requirements in every single circumstance. | ||
+ | |||
+ | Compliant media servers should include a '''size''' element in their artwork URIs, where the size is the image's largest dimension. This allows a control point to ask for an image at a specified size. | ||
+ | |||
+ | The size requested by a control point is a hint for the media server and it does not imply that the media server will satisfy the request. For example a control point might request size=160 but the media server returns size=256 as it is the closest match in its cache. | ||
+ | |||
+ | === Example === | ||
+ | |||
+ | If the original artwork was 400x512, then a media server would provide the following albumArtURI: <uri>?size=512. If it is not possible for the media server to obtain the original resolution then the media server would provide the following albumArtURI: <uri>?size=0. | ||
+ | |||
+ | The presence of the size element tells the control point: | ||
+ | |||
+ | # the media server implements the image scaling extension | ||
+ | # the original size of the image. | ||
+ | |||
+ | Now the control point can request the image at any resolution by using <uri>?size=x, where x is the size it wants. | ||
+ | |||
+ | So, in this example, <uri>?size=1024 gets an 800x1024 image, and <uri>?size=200 gets a 156x200 image. | ||
+ | |||
+ | == Group Information == | ||
+ | |||
+ | Classical music has the concept of a "work" or "composition" consisting of a group of tracks. This concept is not easily represented in a control point using DidlLite. | ||
+ | |||
+ | A new property has been added to the musicTrack item called '''group'''. | ||
+ | |||
+ | A media server would set the the group property of a musicTrack with the value defined by the GROUP tag contained in the metadata of the audio file. | ||
+ | |||
+ | == Disc Information == | ||
+ | |||
+ | A new property has been added to the musicTrack item called '''originalDiscNumber'''. | ||
+ | |||
+ | A new property has been added to the musicAlbum item called '''originalDiscCount'''. | ||
+ | |||
+ | == Replay Gain Information == | ||
+ | |||
+ | Four new properties have been added to the musicTrack item called '''replayGainAlbum''', '''replayGainAlbumPeak''', '''replayGainTrack''', and '''replayGainTrackPeak'''. | ||
− | + | == Dynamic IP Addresses == | |
− | + | At present all media servers return URIs that contain a reference to their IP address, e.g. http://172.20.1.1/music.flac etc. This means that if the media server's IP address were to change across reboots, then any control point or media renderer with URIs that referenced the media server before the reboot will become invalid. | |
− | + | If a user wants to ensure a URI provided by the media server is long lived the host machine running the media server must be assigned a static or dynamic reserved IP address. |
Latest revision as of 09:04, 14 April 2015
Contents
Introduction
The ContentDirectory service has various limitations which become apparent when implementing control points on different hardware platforms. This document aims to outline some ideas that address the various shortcomings of the ContentDirectory specification.
Container map
The current ContentDirectory specification makes it tricky for a control point to display the returned contents in an appropriate, aesthetically pleasing, manner for the content being viewed. This is because the ContentDirectory specification does not allow for a control point to know in advanced what content to expect when browsing through any particular hierarchy.
An example of this might be, at a particular point in the browse hierarchy the ContentDirectory will return a list of albums which in turn will contain a list of tracks. A UI might wish to represent this list of albums as a grid and the album's tracks as a header and a list of the tracks. Currently it is not possible for the UI to know when it gets to a point in a hierarchy where the hierarchy represents a list of albums followed by a list of tracks.
The container map extension allows a media server to express its container hierarchy in advance of the control point navigating it. This is done using an OpenHome vendor extension to the device XML.
Three types of mapped container are defined: browse, link, and search.
The browse map defines named top level containers that represent significant starting points for browsing that can meaningfully be presented in top level tabs of a control point UI. The browse map is expressed within the X_MAP_BROWSE element of X_MAP.
The link map defines containers that can be meaningfully linked to from track or album details. For instance a track will typically have an artist defined. If an entry for "artist" is defined in the link map then it will be possible for the user of a control point to quickly access this artist-related container by clicking on the track's artist text. Similar links might be offered for "genre", "composer", "conductor", etc. The link map is expressed within the X_MAP_LINK element of X_MAP.
The search map defines the different kinds of search containers and the type of results that they produce. The search map is expressed within the X_MAP_SEARCH element of X_MAP.
Browse map
The X_MAP_BROWSE element must contain 1 or more X_MAP_BROWSE_ENTRY elements.
The X_MAP_BROWSE_ENTRY has three child elements.
X_MAP_BROWSE_ENTRY_NAME is a string that can be used by a control point to label a tab containing this browse hierarchy.
X_MAP_BROWSE_ENTRY_ID is the UPnP container id that contains the root of this browse hierarchy. This id is then submitted to the ContentDirectory service using the Browse action as usual. The returned contents are navigated using subsequent Browse request as usual. The difference is that the control point knows in advance what kind of results to expect at each level.
X_MAP_BROWSE_ENTRY_TYPE is a space separated list of strings that maps out the kind of containers that are to be found at each level of this browse hierarchy. For instance, "artist album" represents a browse hierarchy giving a container containing only artist containers, each of which contains only album containers, each of which contains only tracks.
There should be an X_MAP_BROWSE_ENTRY for each root browse hierarchy defined by the media server.
For example:
<X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY_NAME>Genre</X_MAP_BROWSE_ENTRY_NAME> <X_MAP_BROWSE_ENTRY_ID>db/browse/genre</X_MAP_BROWSE_ENTRY_ID> <X_MAP_BROWSE_ENTRY_TYPE>genre artist album</X_MAP_BROWSE_ENTRY_TYPE> </X_MAP_BROWSE_ENTRY>
Link map
The X_MAP_LINK element must contain 1 or more X_MAP_LINK_ENTRY elements.
The X_MAP_LINK_ENTRY has three child elements.
X_MAP_LINK_ENTRY_TAG is a string that defines which type of metadata is the target for this link. e.g. "artist", "genre", "composer", etc. See the type section below.
X_MAP_LINK_ENTRY_ID_PREFIX is a string that is prefix for a UPnP container id. The link can be taken by browsing to the container whose id is the result of appending the associated metadata value to this prefix. For instance, if the prefix for an "artist" link is defined as db/link/artist/, and a track returned anywhere in the media server's library has "Pink Floyd" as its artist. Then the linked container will have an id of db/link/artist/Pink Floyd.
X_MAP_LINK_ENTRY_TYPE represents the type of browse hierarchy returned when taking this type of link. See X_MAP_BROWSE_ENTRY_TYPE for details.
There should be an X_MAP_LINK_ENTRY for each piece of metadata that the media server allows to be linked.
For example:
<X_MAP_LINK_ENTRY> <X_MAP_LINK_ENTRY_TAG>artist</X_MAP_LINK_ENTRY_TAG> <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/artist/</X_MAP_LINK_ENTRY_ID_PREFIX> <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> </X_MAP_LINK_ENTRY>
The example above defines a browse hierarchy that is created when linking from an artist name. The hierarchy created provides a list of linked artist albums which in turn provide a list of tracks.
Search map
The X_MAP_SEARCH element must contain 1 or more X_MAP_SEARCH_ENTRY elements.
The X_MAP_SEARCH_ENTRY has three child elements.
X_MAP_SEARCH_ENTRY_NAME is a string that can be used by a control point to label a tab containing these search results.
X_MAP_SEARCH_ENTRY_ID_PREFIX is a string that is a prefix for a UPnP container id. The search results can be found by browsing to the container whose id is the result of appending the search string to this prefix. For instance, if the prefix for an "album" search is defined as db/search/album/, and the search string is "blue", then the search results container will have an id of db/search/album/blue.
X_MAP_SEARCH_ENTRY_TYPE represents the type of browse hierarchy returned when taking this type of search. See X_MAP_BROWSE_ENTRY_TYPE for details.
There should be an X_MAP_SEARCH_ENTRY for each type of search offered by the media server.
For example:
<X_MAP_SEARCH_ENTRY> <X_MAP_SEARCH_ENTRY_NAME>Artist</X_MAP_SEARCH_ENTRY_NAME> <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/artist/</X_MAP_SEARCH_ENTRY_ID_PREFIX> <X_MAP_SEARCH_ENTRY_TYPE>artist album</X_MAP_SEARCH_ENTRY_TYPE> </X_MAP_SEARCH_ENTRY>
The example above defines a browse hierarchy that is created when searching for an artist. The hierarchy created provides a list of artists, which in turn provide a list of albums, which in turn provide a list of tracks.
Types
The list of allowed types for X_BROWSE_ENTRY_TYPE, X_MAP_LINK_ENTRY_TAG, X_LINK_ENTRY_TYPE, and X_SEARCH_ENTRY_TYPE
genre artist composer conductor album year mixed
mixed is a special value that represents a container that has mixed entries. It is not a valid type for the X_MAP_LINK_ENTRY_TAG element.
Example device XML
<root xmlns="urn:schemas-upnp-org:device-1-0"> <specVersion> <major>1</major> <minor>1</minor> </specVersion> <device> <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType> <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMS-1.50</dlna:X_DLNADOC> <dlna:X_DLNACAP xmlns:dlna="urn:schemas-dlna-org:device-1-0">av-upload,image-upload,audio-upload</dlna:X_DLNACAP> <openhome:X_MAP xmlns:openhome="http://www.openhome.org"> <X_MAP_BROWSE> <X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY_NAME>Albums</X_MAP_BROWSE_ENTRY_NAME> <X_MAP_BROWSE_ENTRY_ID>db/browse/albums</X_MAP_BROWSE_ENTRY_ID> <X_MAP_BROWSE_ENTRY_TYPE>album</X_MAP_BROWSE_ENTRY_TYPE> </X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY_NAME>Artists</X_MAP_BROWSE_ENTRY_NAME> <X_MAP_BROWSE_ENTRY_ID>db/browse/artists</X_MAP_BROWSE_ENTRY_ID> <X_MAP_BROWSE_ENTRY_TYPE>artist album</X_MAP_BROWSE_ENTRY_TYPE> </X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY> <X_MAP_BROWSE_ENTRY_NAME>Folders</X_MAP_BROWSE_ENTRY_NAME> <X_MAP_BROWSE_ENTRY_ID>db/browse/folders</X_MAP_BROWSE_ENTRY_ID> <X_MAP_BROWSE_ENTRY_TYPE>mixed</X_MAP_BROWSE_ENTRY_TYPE> </X_MAP_BROWSE_ENTRY> </X_MAP_BROWSE> <X_MAP_LINK> <X_MAP_LINK_ENTRY> <X_MAP_LINK_ENTRY_TAG>artist</X_MAP_LINK_ENTRY_TAG> <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/artist/</X_MAP_LINK_ENTRY_ID_PREFIX> <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> </X_MAP_LINK_ENTRY> <X_MAP_LINK_ENTRY> <X_MAP_LINK_ENTRY_TAG>composer</X_MAP_LINK_ENTRY_TAG> <X_MAP_LINK_ENTRY_ID_PREFIX>db/link/composer/</X_MAP_LINK_ENTRY_ID_PREFIX> <X_MAP_LINK_ENTRY_TYPE>album</X_MAP_LINK_ENTRY_TYPE> </X_MAP_LINK_ENTRY> </X_MAP_LINK> <X_MAP_SEARCH> <X_MAP_SEARCH_ENTRY> <X_MAP_SEARCH_ENTRY_NAME>Artist</X_MAP_SEARCH_ENTRY_NAME> <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/artist/</X_MAP_SEARCH_ENTRY_ID_PREFIX> <X_MAP_SEARCH_ENTRY_TYPE>artist album</X_MAP_SEARCH_ENTRY_TYPE> </X_MAP_SEARCH_ENTRY> <X_MAP_SEARCH_ENTRY> <X_MAP_SEARCH_ENTRY_NAME>Tracks</X_MAP_SEARCH_ENTRY_NAME> <X_MAP_SEARCH_ENTRY_ID_PREFIX>db/search/all/</X_MAP_SEARCH_ENTRY_ID_PREFIX> <X_MAP_SEARCH_ENTRY_TYPE></X_MAP_SEARCH_ENTRY_TYPE> </X_MAP_SEARCH_ENTRY> </X_MAP_SEARCH> </openhome:X_MAP> <presentationURL>http://10.2.1.170:4000/res/linn.co.uk.kazooserver/index.html</presentationURL> <friendlyName>Linn Kazoo Server [R&D Mac Mini]</friendlyName> <manufacturer>Linn</manufacturer> <manufacturerURL>http://www.linn.co.uk</manufacturerURL> <modelName>Kazoo Server</modelName> <modelURL>http://oss.linn.co.uk/trac/wiki/KazooServer</modelURL> <UDN>uuid:ac3d630e37b5f11ff5cdd23c0f5a7400</UDN> <iconList> <icon> <mimetype>image/png</mimetype> <width>65</width> <height>65</height> <depth>32</depth> <url>ac3d630e37b5f11ff5cdd23c0f5a7400/resource/icon/icon</url> </icon> </iconList> <serviceList> <service> <serviceType>urn:av-openhome-org:service:PlaylistManager:1</serviceType> <serviceId>urn:av-openhome-org:serviceId:PlaylistManager</serviceId> <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/av.openhome.org-PlaylistManager-1/service.xml</SCPDURL> <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/av.openhome.org-PlaylistManager-1/control</controlURL> <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/av.openhome.org-PlaylistManager-1/event</eventSubURL> </service> <service> <serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType> <serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId> <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/upnp.org-ContentDirectory-1/service.xml</SCPDURL> <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ContentDirectory-1/control</controlURL> <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ContentDirectory-1/event</eventSubURL> </service> <service> <serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType> <serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId> <SCPDURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/Upnp/upnp.org-ConnectionManager-1/service.xml</SCPDURL> <controlURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ConnectionManager-1/control</controlURL> <eventSubURL>/ac3d630e37b5f11ff5cdd23c0f5a7400/upnp.org-ConnectionManager-1/event</eventSubURL> </service> </serviceList> </device> </root>
Index maps
Large lists are difficult to navigate, especially on mobile devices. Mobile devices added the idea of an index map to improve this situation. The index map allows a users to jump to different sections in a large list, similar to what is possible with a scrollbar on desktops.
In order for a control point to generate an index map for any particular level in a ContentDirectory's hierarchy it first needs to download all the objects in the container, figure out if they are sorted and then calculate the index map. This means that a user will need to wait, perhaps minutes, before an index map is able to be presented on the UI.
The media server can optionally return an index map for container that are in alphabetical order. This implemented through a OpenHome vendor extension of the DIDL-Lite XML. Below shows an example DIDL-Lite with an index map included.
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"> <container id="db/ba37a2ac24efa676c8676aab71a6cdf074" parentID="0" restricted="true"> <dc:title xmlns:dc="http://purl.org/dc/elements/1.1/">Worlds Apart [Deluxe Edition]</dc:title> <upnp:udn xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">ac3d630e37b5f11ff5cdd23c0f5a7400</upnp:udn> <upnp:class xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">object.container.album.musicAlbum</upnp:class> <upnp:artist xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">...And You Will Know Us by the Trail of Dead</upnp:artist> <upnp:albumArtURI>http://10.2.1.170:4000/linn.co.uk.kazooserver/ms/artwork/37a2ac2?size=0</upnp:albumArtURI> </container> <desc nameSpace="openhome.org"> <openhome.org:indexmap>0 10 10 10 10 10 0 0 0 0 10 12 1 10 10 10 12 17 18 1 0 20 0 20 20 2 2 24</indexmap> </desc> </DIDL-Lite>
The index map contains a space separated list of 28 number representing the total number of items that begin with that letter. #, represents everything below A, largely digits and punctuation and + represents everything above Z, largely international characters not collatable within the roman alphabet.
# A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +
Image Resolution
Control points running on different platforms have different memory limits and display technologies. This means that a control point on a PC might want to display artwork at a high resolution, while a control point on a PDA might want to display artwork at a much lower resolution.
Media servers often try to solve this problem using one of the following two methods:
- A configurable parameter that scales all artwork to a user defined size
- A profile system where a user can create profiles for each class of control point they have and configure a parameter that scales all artwork to a user defined size per profile
The first solution is highly problematic because it limits the resolution of artwork across the whole network. But a single network very often contains control points that can display high resolution images AND control points that can't.
The second solution is just architecturally poor, turning the relationship between a control point and a media server on its head. Why should the media server try to infer what a control point needs through configuration when the control point is perfectly capable of telling the media server its exact requirements in every single circumstance.
Compliant media servers should include a size element in their artwork URIs, where the size is the image's largest dimension. This allows a control point to ask for an image at a specified size.
The size requested by a control point is a hint for the media server and it does not imply that the media server will satisfy the request. For example a control point might request size=160 but the media server returns size=256 as it is the closest match in its cache.
Example
If the original artwork was 400x512, then a media server would provide the following albumArtURI: <uri>?size=512. If it is not possible for the media server to obtain the original resolution then the media server would provide the following albumArtURI: <uri>?size=0.
The presence of the size element tells the control point:
- the media server implements the image scaling extension
- the original size of the image.
Now the control point can request the image at any resolution by using <uri>?size=x, where x is the size it wants.
So, in this example, <uri>?size=1024 gets an 800x1024 image, and <uri>?size=200 gets a 156x200 image.
Group Information
Classical music has the concept of a "work" or "composition" consisting of a group of tracks. This concept is not easily represented in a control point using DidlLite.
A new property has been added to the musicTrack item called group.
A media server would set the the group property of a musicTrack with the value defined by the GROUP tag contained in the metadata of the audio file.
Disc Information
A new property has been added to the musicTrack item called originalDiscNumber.
A new property has been added to the musicAlbum item called originalDiscCount.
Replay Gain Information
Four new properties have been added to the musicTrack item called replayGainAlbum, replayGainAlbumPeak, replayGainTrack, and replayGainTrackPeak.
Dynamic IP Addresses
At present all media servers return URIs that contain a reference to their IP address, e.g. http://172.20.1.1/music.flac etc. This means that if the media server's IP address were to change across reboots, then any control point or media renderer with URIs that referenced the media server before the reboot will become invalid.
If a user wants to ensure a URI provided by the media server is long lived the host machine running the media server must be assigned a static or dynamic reserved IP address.