#LyX 1.5.5 created this file. For more info see http://www.lyx.org/
\lyxformat 276
\begin_document
\begin_header
\textclass docbook
\language english
\inputencoding auto
\font_roman default
\font_sans default
\font_typewriter default
\font_default_family default
\font_sc false
\font_osf false
\font_sf_scale 100
\font_tt_scale 100
\graphics default
\paperfontsize default
\papersize default
\use_geometry false
\use_amsmath 0
\use_esint 0
\cite_engine basic
\use_bibtopic false
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language english
\papercolumns 1
\papersides 1
\paperpagestyle default
\tracking_changes false
\output_changes false
\author "" 
\author "" 
\end_header

\begin_body

\begin_layout Title
MediaTomb Scripting
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<copyright>
\end_layout

\begin_layout Standard

  <year>2005</year>
\end_layout

\begin_layout Standard

  <holder>Gena Batsyan</holder>
\end_layout

\begin_layout Standard

  <holder>Sergey Bostandzhyan</holder>
\end_layout

\begin_layout Standard

</copyright>
\end_layout

\begin_layout Standard

<copyright>
\end_layout

\begin_layout Standard

  <year>2006-2008</year>
\end_layout

\begin_layout Standard

  <holder>Gena Batsyan</holder>
\end_layout

\begin_layout Standard

  <holder>Sergey Bostandzhyan</holder>
\end_layout

\begin_layout Standard

  <holder>Leonhard Wimmer</holder>
\end_layout

\begin_layout Standard

</copyright>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<releaseinfo>This documentation is valid for MediaTomb version 0.12.0.</releaseinfo
>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<legalnotice>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</legalnotice>
\end_layout

\end_inset


\end_layout

\begin_layout Section
Introduction
\end_layout

\begin_layout Standard
MediaTomb allows you to customize the structure of how your media is being
 presented to your renderer.
 One of the most important features introduced since the version 0.8 are
 the virtual containers and virtual items.
 Let's think of possible scenarios:
\end_layout

\begin_layout Itemize
you may want to separate your content by music, photo, video, maybe create
 a special container with all non playable stuff
\end_layout

\begin_layout Itemize
you may want your music to be sorted by genre, year, artist, album, or maybe
 by starting letters, so you can more easily find your favorite song when
 browsing the server
\end_layout

\begin_layout Itemize
you want to have your photos that you took with your favorite digital camera
 to appear in a special folder, or maybe you even want to separate the photos
 that you took with flash-on from the ones that you made without flash
\end_layout

\begin_layout Itemize
your media player does not support video, so you do not even want to see
 the Video container
\end_layout

\begin_layout Itemize
it's up to your imagination :)
\end_layout

\begin_layout Standard
The scenarios described above and much more can be achieved with the help
 of an import script.
 
\end_layout

\begin_layout Standard
Version 0.10.0 introduces a playlist parsing feature, which is also handled
 by scripting and version 0.12.0 adds a script for creating a virtual layout
 out of a DVD iso image.
\end_layout

\begin_layout Section
How It Works
\end_layout

\begin_layout Standard
This section will give you some overview on how virtual objects work and
 on how they are related to scripting.
\end_layout

\begin_layout Description
NOTE: In order to use the import scripting feature you have to change the
 layout type from 
\emph on
builtin
\emph default
 to 
\emph on
js
\emph default
 in config.xml !
\end_layout

\begin_layout Subsection
Understanding Virtual Objects.
\end_layout

\begin_layout Standard
When you add a file or directory to the database via the web interface several
 things happen.
\end_layout

\begin_layout Enumerate
The object is inserted into the PC Directory.
 PC Directory is simply a special non-removable container.
 Any media file added will have an entry inside the PC Directory tree.
 PC Directory's hierarchy reflects the file system hierarchy, all objects
 inside the PC Directory including itself are NON-VIRTUAL objects.
 All virtual objects may have a different title, description, etc., but they
 are still references to objects in the PC-Directory.
 That's why it is not possible to change a location of a virtual object
 - the only exceptions are URL items and Active items.
\end_layout

\begin_layout Enumerate
Once an item is added to the PC Directory it is forwarded to the virtual
 object engine.
 The virtual object engine's mission is to organize and present the media
 database in a logical hierarchy based on the available metadata of the
 items.
\end_layout

\begin_layout Standard
Each UPnP server implements this so called virtual object hierarchy in a
 different way.
 Audio files are usually sorted by artist, album, some servers may just
 present a view similar to the file system and so on.
 Most servers have strong limitations on the structure of the virtual containers
, they usually offer a predefined layout of data and the user has to live
 with it.
 In MediaTomb we try to address this shortcoming by introducing the scriptable
 virtual object engine.
 It is designed to be:
\end_layout

\begin_layout Itemize
maximally flexible
\end_layout

\begin_layout Itemize
easily customizable and extendable
\end_layout

\begin_layout Itemize
robust and efficient
\end_layout

\begin_layout Standard
We try to achieve these goals by embedding a scripting runtime environment
 that allows the execution of ECMAScript-262 conform scripts better known
 as JavaScript.
 We are using Mozilla's JavaScript implementation called SpiderMonkey, it
 is a stand-alone easily embeddable javascript engine, supporting JavaScript
 versions 1.0 through 1.4.
\end_layout

\begin_layout Subsection
Theory Of Operation
\end_layout

\begin_layout Standard
After an item is added to the PC Directory it is automatically fed as input
 to the import script.
 The script then creates one or more virtual items for the given original
 item.
 Items created from scripts are always marked virtual.
 
\end_layout

\begin_layout Standard
When the virtual object engine gets notified of an added item, following
 happens: a javascript object is created mirroring the properties of the
 item.
 The object is introduced to the script environment and bound to the predefined
 variable 'orig'.
 This way a variable orig is always defined for every script invocation
 and represents the original data of the added item.
 Then the script is invoked.
\end_layout

\begin_layout Standard
In the current implementation, if you modify the script then you will have
 to restart the server for the new logic to take effect.
 Note, that the script is only triggered when new objects are added to the
 database, also note that the script does not modify any objects that already
 exist in the database - it only processes new objects that are being added.
 When a playlist item is encountered, it is automatically fed as input to
 the playlist script.
 The playlist script attempts to parse the playlist and adds new item to
 the database, the item is then processed by the import script.
\end_layout

\begin_layout Section
Global Variables And Constants
\end_layout

\begin_layout Standard
In this section we will introduce the properties of the object that will
 be processed by the script, as well as functions that are offered by the
 server.
\end_layout

\begin_layout Subsection
The Media Object
\end_layout

\begin_layout Standard
As described in Section 2.2, each time an item is added to the database the
 import script is invoked.
 So, one script invocation processes exactly one non virtual item, and creates
 a number of virtual items and containers.
 The original item is made available in the form of the global variable
 'orig'.
 Additionally, when the object being imported is a playlist, it is made
 available to the playlist parser script in the form of the global variable
 'playlist'.
 It is usually a good idea to only read from these variables and to create
 and only modify local copies.
 
\end_layout

\begin_layout Description
Note: modifying the properties of the orig object will not propagate the
 changes to the database, only a call to the addCdsObject() will permanently
 add the object.
\end_layout

\begin_layout Subsubsection
General Properties
\end_layout

\begin_layout Standard
Here is a list of properties of an object, you can set them you create a
 new object or when you modify a copy of the 'orig' object.
 
\end_layout

\begin_layout Standard

\emph on
RW 
\emph default
means read/write, i.e.
 - changes made to that property will be transferred into the database.
\end_layout

\begin_layout Standard

\emph on
RO
\emph default
 means, that this is a read only property, any changes made to it will get
 lost.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.objectType
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
This defines the object type, following types are available:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_CONTAINER
\end_layout

\begin_layout Standard
Object is a container.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM
\end_layout

\begin_layout Standard
Object is an item.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ACTIVE_ITEM
\end_layout

\begin_layout Standard
Object is an active item.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM_EXTERNAL_URL
\end_layout

\begin_layout Standard
Object is a link to a resource on the Internet.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM_INTERNAL_URL
\end_layout

\begin_layout Standard
Object is an internal link.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.title
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
This is the title of the original object, since the object represents an
 entry in the PC-Directory, the title will be set to it's file name.
 This field corresponds to dc:title in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.id
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RO
\end_layout

\begin_layout Standard
The object ID, make sure to set all refID's (reference IDs) of your virtual
 objects to that ID.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.parentID
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RO
\end_layout

\begin_layout Standard
The object ID of the parent container.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.upnpclass
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
The UPnP class of the item, this corresponds to upnp:class in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.location
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RO
\end_layout

\begin_layout Standard
Location on disk, given by the absolute path and file name.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.theora
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RO
\end_layout

\begin_layout Standard
This property is a boolean value, it is non zero if the particular item
 is of type OGG Theora.
 This is useful to allow proper sorting of media and thus placing OGG Vorbis
 into the Audio container and OGG Theora into the Video container.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.onlineservice
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RO
\end_layout

\begin_layout Standard
Identifies if the item belongs to an online service and thus has extended
 properties.
 Following types are available:
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
ONLINE_SERVICE_NONE
\end_layout

\begin_layout Standard
The item does not belong to an online service and does not have extended
 properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
ONLINE_SERVICE_YOUTUBE
\end_layout

\begin_layout Standard
The item belongs to the YouTube service and has extended properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
ONLINE_SERVICE_WEBORAMA
\end_layout

\begin_layout Standard
The item belongs to the Weborama service and has extended properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
ONLINE_SERVICE_APPLE_TRAILERS
\end_layout

\begin_layout Standard
The item belongs to the Apple Trailers service and has extended properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.mimetype
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
Mimetype of the object.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
Array holding the metadata that was extracted from the object (i.e.
 id3/exif/etc.
 information)
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_TITLE]
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
Extracted title (for example the id3 title if the object is an mp3 file),
 if you want that your new virtual object is displayed under this title
 you will have to set obj.title = orig.meta[M_TITLE]
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_ARTIST]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Artist information, this corresponds to upnp:artist in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_ALBUM]
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
Album information, this corresponds to upnp:album in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_DATE]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Date, must be in the format of YYYY-MM-DD (required by the UPnP spec), this
 corresponds to dc:date in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_GENRE]
\end_layout

\begin_layout Standard

\family typewriter
\emph on
RW
\end_layout

\begin_layout Standard
Genre of the item, this corresponds to upnp:genre in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_DESCRIPTION]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Description of the item, this corresponds to dc:description in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_REGION]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Region description of the item, this corresponds to upnp:region in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_TRACKNUMBER]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Track number of the item, this corresponds to upnp:originalTrackNumber in
 the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_AUTHOR]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Author of the media, this corresponds to upnp:author in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_DIRECTOR]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Director of the media, this corresponds to upnp:director in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_PUBLISHER]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Director of the media, this corresponds to dc:publisher in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_RATING]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Director of the media, this corresponds to upnp:rating in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_ACTOR]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Director of the media, this corresponds to upnp:actor in the DIDL-Lite XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.meta[M_PRODUCER]
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
Director of the media, this corresponds to upnp:producer in the DIDL-Lite
 XML.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Array holding the so called auxiliary data.
 Aux data is metadata that is not part of UPnP, for example - this can be
 a camera model that was used to make a photo, or the information if the
 photo was taken with or without flash.
 Currently aux data can be gathered from libexif and libextractor (see the
 Import section in the main documentation for more details).
 So, this array will hold the tags that you specified in your config.xml,
 allowing you to create your virtual structure according to your liking.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.playlistOrder
\end_layout

\begin_layout Standard

\emph on
RW
\end_layout

\begin_layout Standard
This property is only available if the object is being created by the playlist
 script.
 It's similar to ID3 track number, but is used to set the position of the
 newly created object inside a parsed playlist container.
 Usually you will increment the number for each new object that you create
 while parsing the playlist, thus ensuring that the resulting order is the
 same as in the original playlist.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsubsection
YouTube Properties
\end_layout

\begin_layout Standard
When the obj.onlineservice variable equals ONLINE_SERVICE_YOUTUBE the item
 has the following additional properties:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.yt_request
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Identifies the YouTube request type, following types are available:
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_NONE
\end_layout

\begin_layout Standard
No request/invalid.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_USER_FAVORITES
\end_layout

\begin_layout Standard
The item was created as a result of a favorites request.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_VIDEO_SEARCH
\end_layout

\begin_layout Standard
The item was created as a result of a search request.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_USER_UPLOADS
\end_layout

\begin_layout Standard
The item was created as a result of a request for videos that were uploaded
 by a particular user.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_STANDARD_FEED
\end_layout

\begin_layout Standard
The item was created as a result of a request for one of the standard feeds.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_USER_PLAYLISTS
\end_layout

\begin_layout Standard
The item was created as a result of a request for users playlists.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
YOUTUBE_REQUEST_USER_SUBSCRIPTIONS
\end_layout

\begin_layout Standard
The item was created as a result of for users subscriptions.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
The following aux keys can be used to retrieve additional information about
 the item, the data is stored in the form of strings.
 Note, that depending on the requests some tags may not be set and will
 return empty values.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_KEYWORDS]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains a space separated list of keywords for the particular item.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_AVG_RATING]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the average rating value.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_AUTHOR]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the author name.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_FEED]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the name of the feed.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_VIEW_COUNT]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the view count of the video on the YouTube website.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_REGION]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the name of the region.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_RATING_COUNT]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the rating count of the video on the YouTube website.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_REQUEST]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the name of the request that produced this item (i.e.
 Favorites, Popular, etc.), this is the human readable representation of
 the orig.yt_request property.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_SUBREQUEST_NAME]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the additional name that accompanies the request, it is only set
 for the playlist and subcription requests.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
orig.aux[YOUTUBE_AUXDATA_CATEGORY]
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Contains the name of the category of the item.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsubsection
Weborama Properties
\end_layout

\begin_layout Standard
When the obj.onlineservice variable equals ONLINE_SERVICE_WEBORAMA the item
 has the following additional aux property:
\end_layout

\begin_layout Code
orig.aux[WEBORAMA_AUXDATA_REQUEST_NAME]
\end_layout

\begin_layout Standard
This property holds the name of the request that generated this object,
 it is the name that you specify in the config.xml file, i.e.
 in the below example the value of orig.aux[WEBORAMA_AUXDATA_REQUEST_NAME]
 will be 'My Playlist':
\end_layout

\begin_layout Code
<playlist name="My Playlist" type="playlist" mood="dark"/>
\end_layout

\begin_layout Subsubsection
Apple Trailers Properties
\end_layout

\begin_layout Standard
When the obj.onlineservice variable equals ONLINE_SERVICE_APPLE_TRAILERS
 the item has the following additional aux property:
\end_layout

\begin_layout Code
orig.aux[APPLE_TRAILERS_AUXDATA_POST_DATE]
\end_layout

\begin_layout Standard
This property holds the date when the trailer was posted, the date format
 is YYYY-MM-DD.
\end_layout

\begin_layout Description
Note: the orig.meta[M_DATE] property holds the release date of the movie.
\end_layout

\begin_layout Subsubsection
DVD Properties
\end_layout

\begin_layout Standard
Version 0.12.0 introduces an additional import script for DVD images.
 The DVD image is parsed with the help of libdvdread, the information about
 the available titles, chapters, languages, etc.
 is gathered and provided to the DVD import script.
 The usual object properties apply here as well, however the dvd object
 offers several extensions that can be accessed via the aux property:
\end_layout

\begin_layout Code
dvd.aux[DVD]
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
This is an array that contains information about titles that are found on
 the DVD.
 The length of the array (and thus the number of available titles can be
 retrieved by:
\end_layout

\begin_layout Code
dvd.aux[DVD].titles.length
\end_layout

\begin_layout Standard
Further, being a normal JavaScript array it supports all associated JS functions.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].audio_tracks
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Each title object in the titles array provides information about available
 audio tracks, the audio_tracks is an array as well.
 The t_index variable is only used as an example in this case and represents
 an integer index value in the range:
\end_layout

\begin_layout Code
dvd.aux[DVD].titles.length > t_index >= 0
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].audio_tracks[a_index].format
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
A string, containing the format name of the audio track (i.e.
 ac3, dts, etc.).
 The a_index variable is only used as an example, it represents an integer
 index value in the range:
\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].audio_tracks.length > a_index >= 0
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].audio_tracks[a_index].language
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
A string, containing the name of the language of the audio track.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].chapters
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
This property is an array which contains chapter information for the particular
 title.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].chapters[c_index].duration
\end_layout

\begin_layout Standard

\emph on
RO
\end_layout

\begin_layout Standard
Duration from the start of the chapter to the end of the movie.
 Chapter at index 0 will always have the duration of the whole title.
 The c_index variable is only used as an example, it represents an integer
 index value in the range:
\end_layout

\begin_layout Code
dvd.aux[DVD].titles[t_index].chapters.length > c_index >= 0
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsection
Constants
\end_layout

\begin_layout Standard
Actually there are no such things as constants in JS, so those are actually
 predefined global variables that are set during JS engine initialization.
 Do not assign any values to them, otherwise following script invocation
 will be using wrong values.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_CONTAINER
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.container
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_CONTAINER_MUSIC_ARTIST
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.container.person.musicArtist
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_CONTAINER_MUSIC_GENRE
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.container.genre.musicGenre
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_CONTAINER_MUSIC_ALBUM
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.container.album.musicAlbum
\end_layout

\begin_layout Description
Note: this container class will be treated by the server in a special way,
 all music items in this container will be sorted by ID3 track number.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_PLAYLIST_CONTAINER
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.container.playlistContainer
\end_layout

\begin_layout Description
Note: this container class will be treated by the server in a special way,
 all items in this container will be sorted by the number specified in the
 playlistOrder property (this is set when an object is created by the playlist
 script).
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_ITEM
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.item
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_ITEM_MUSIC_TRACK
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.item.audioItem.musicTrack
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_ITEM_VIDEO
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.item.videoItem
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
UPNP_CLASS_ITEM_IMAGE
\end_layout

\begin_layout Standard

\emph on
Type: string
\end_layout

\begin_layout Standard

\emph on
Value: object.item.imageItem
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_CONTAINER
\end_layout

\begin_layout Standard

\emph on
Type: integer
\end_layout

\begin_layout Standard

\emph on
Value: 1
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM
\end_layout

\begin_layout Standard

\emph on
Type: integer
\end_layout

\begin_layout Standard

\emph on
Value: 2
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ACTIVE_ITEM
\end_layout

\begin_layout Standard

\emph on
Type: integer
\end_layout

\begin_layout Standard

\emph on
Value: 4
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM_EXTERNAL_URL
\end_layout

\begin_layout Standard

\emph on
Type: integer
\end_layout

\begin_layout Standard

\emph on
Value: 8
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
OBJECT_TYPE_ITEM_INTERNAL_URL
\end_layout

\begin_layout Standard

\emph on
Type: integer
\end_layout

\begin_layout Standard

\emph on
Value: 16
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Section
Functions
\end_layout

\begin_layout Standard
The server offers various native functions that can be called from the scripts,
 additionally there are some js helper functions that can be used.
\end_layout

\begin_layout Subsection
Native Server Functions
\end_layout

\begin_layout Standard
The so called native functions are implemented in C++ in the server and
 can be called from the scripts.
\end_layout

\begin_layout Subsubsection
Native Functions Available To All Scripts
\end_layout

\begin_layout Standard
The server offers three functions which can be called from within the import
 and/or the playlist script:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
addCdsObject(object, containerChain, lastContainerClass);
\end_layout

\begin_layout Standard
This function adds a virtual object to the server database, the path in
 the database is defined by the containerChain parameter.
 The third argument is optional, it allows to set the upnp:class of the
 last container in the chain.
\end_layout

\begin_layout Standard
Parameters:
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
object
\end_layout

\begin_layout Standard
A virtual object that is either a copy of or a reference to 'orig', see
 Section 3.2 for a list of properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
containerChain
\end_layout

\begin_layout Standard
A string, defining where the object will be added in the database hierarchy.
 The containers in the chain are separated by a slash '/', for example,
 a value of '/Audio/All Music' will add the object to the Audio, All Music
 container in the server hierarchy.
 Make sure to properly escape the slash characters in container names.
 You will find more information on container chain escaping later in this
 chapter.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
lastContainerClass
\end_layout

\begin_layout Standard
A string, defining the upnp:class of the container that appears last in
 the chain.
 This parameter can be omitted, in this case the default value 'object.container'
 will be taken.
 Setting specific upnp container classes is useful to define the special
 meaning of a particular container; for example, the server will always
 sort songs by track number if upnp class of a container is set to 'object.contai
ner.album.musicAlbum'.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
copyObject(originalObject);
\end_layout

\begin_layout Standard
This function returns a copy of the virtual object.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
print(...);
\end_layout

\begin_layout Standard
This function is useful for debugging scripts, it simply prints to the standard
 output.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
f2i(string)
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
m2i(string)
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
p2i(string)
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
j2i(string)
\end_layout

\begin_layout Standard
The above set of functions converts predefined characters sets to UTF-8.
 The 'from' charsets can be defined in the server configuration:
\end_layout

\begin_layout Itemize
f2i: filesystem charset to internal
\end_layout

\begin_layout Itemize
m2i: metadata charset to internal
\end_layout

\begin_layout Itemize
j2i: js charset to internal
\end_layout

\begin_layout Itemize
p2i: playlist charset to internal
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsubsection
Native Functions Available To The Playlist Script
\end_layout

\begin_layout Standard
The following function is only available to the playlist script.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
readln();
\end_layout

\begin_layout Standard
This function reads and returns exactly one line of text from the playlist
 that is currently being processed, end of line is identified by carriage
 return/line feed characters.
 Each subsequent call will return the next line, there is no way to go back.
\end_layout

\begin_layout Standard
The idea is, that you can process your playlist line by line and gather
 the required information to create new objects which can be added to the
 database.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsubsection
Native Functions Available To The DVD Import Script
\end_layout

\begin_layout Standard
The following function is only available to the DVD import script.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
addCdsObject(object, containerChain, lastContainerClass);
\end_layout

\begin_layout Standard
This function adds a virtual object to the server database, the path in
 the database is defined by the containerChain parameter.
 The third argument is optional, it allows to set the upnp:class of the
 last container in the chain.
\end_layout

\begin_layout Standard
Parameters:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
object
\end_layout

\begin_layout Standard
A virtual object that is either a copy of or a reference to 'orig', see
 Section 3.2 for a list of properties.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
containerChain
\end_layout

\begin_layout Standard
A string, defining where the object will be added in the database hierarchy.
 The containers in the chain are separated by a slash '/', for example,
 a value of '/Audio/All Music' will add the object to the Audio, All Music
 container in the server hierarchy.
 Make sure to properly escape the slash characters in container names.
 You will find more information on container chain escaping later in this
 chapter.
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
lastContainerClass
\end_layout

\begin_layout Standard
A string, defining the upnp:class of the container that appears last in
 the chain.
 This parameter can be omitted, in this case the default value 'object.container'
 will be taken.
 Setting specific upnp container classes is useful to define the special
 meaning of a particular container; for example, the server will always
 sort songs by track number if upnp class of a container is set to 'object.contai
ner.album.musicAlbum'.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
addDVDObject(dvd, t, c, a, createContainerChain(chain));
\end_layout

\begin_layout Standard
This function reads and returns exactly one line of text from the playlist
 that is currently being processed, end of line is identified by carriage
 return/line feed characters.
 Each subsequent call will return the next line, there is no way to go back.
\end_layout

\begin_layout Standard
The idea is, that you can process your playlist line by line and gather
 the required information to create new objects which can be added to the
 database.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Subsection
Helper Functions
\end_layout

\begin_layout Standard
There is a set of helper JavaScript functions which reside in the common.js
 script.
 They can be used by the import and by the playlist script.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

<itemizedlist><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code
function escapeSlash(name);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Standard
The first function escapes slash '/' characters in a string.
 This is necessary, because the container chain is defined by a slash separated
 string, where slash has a special meaning - it defines the container hierarchy.
 That means, that slashes that appear in the object's title need to be properly
 escaped.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Code

\end_layout

\begin_layout Standard
The following function makes it easier to work with container chains; it
 takes an array of container names as argument, makes sure that the names
 are properly escaped and adds the slash separators as necessary.
 It returns a string that is formatted to be used as a parameter for the
 addCdsObject function.
\end_layout

\begin_layout Code
function createContainerChain(arr) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var path = '';
\end_layout

\begin_layout Code
    for (var i = 0; i < arr.length; i++)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        path = path + '/' + escapeSlash(arr[i]);     
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
    return path; 
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
This function retrieves the year from a yyyy-mm-dd formatted string.
\end_layout

\begin_layout Code
function getYear(date) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var matches = date.match(/^([0-9]{4})-/);
\end_layout

\begin_layout Code
    if (matches)
\end_layout

\begin_layout Code
        return matches[1];
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
        return date;
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem><listitem>
\end_layout

\end_inset


\end_layout

\begin_layout Standard
This function identifies the type of the playlist by the mimetype, it is
 used in the playlist script to select an appropriate parser.
\end_layout

\begin_layout Code
function getPlaylistType(mimetype) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    if (mimetype == 'audio/x-mpegurl') 
\end_layout

\begin_layout Code
        return 'm3u'; 
\end_layout

\begin_layout Code
    if (mimetype == 'audio/x-scpls') 
\end_layout

\begin_layout Code
        return 'pls'; 
\end_layout

\begin_layout Code
    return ''; 
\end_layout

\begin_layout Code
} 
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Standard

</listitem></itemizedlist>
\end_layout

\end_inset


\end_layout

\begin_layout Section
Walkthrough
\end_layout

\begin_layout Standard
Now it is time to take a closer look at the default scripts that are supplied
 with MediaTomb.
 Usually it is installed in the /usr/share/mediatomb/js/ directory, but
 you will also find it in scripts/js/ in the MediaTomb source tree.
\end_layout

\begin_layout Description
Note: this is not a JavaScript tutorial, if you are new to JS you should
 probably make yourself familiar with the language.
\end_layout

\begin_layout Subsection
Import Script
\end_layout

\begin_layout Standard
We start with a walkthrough of the default import script, it is called import.js
 in the MediaTomb distribution.
\end_layout

\begin_layout Standard
Below are the import script functions that organize our content in the database
 by creating the virtual structure.
 Each media type - audio, image and video is handled by a separate function.
\end_layout

\begin_layout Subsubsection
Audio Content Handler
\end_layout

\begin_layout Standard
The biggest one is the function that handles audio - the reason is simple:
 mp3 files offer a lot of metadata like album, artist, genre, etc.
 information, this allows us to create a nice container layout.
\end_layout

\begin_layout Code
function addAudio(obj) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var desc = '';
\end_layout

\begin_layout Code
    var artist_full;
\end_layout

\begin_layout Code
    var album_full;
\end_layout

\begin_layout Standard
First we will gather all the metadata that is provided by our object, of
 course it is possible that some fields are empty - we will have to check
 that to make sure that we handle this case correctly.
    
\end_layout

\begin_layout Code
    var title = obj.meta[M_TITLE];
\end_layout

\begin_layout Standard
Note the difference between obj.title and obj.meta[M_TITLE] - while object.title
 will originally be set to the file name, obj.meta[M_TITLE] will contain
 the parsed title - in this particular example the ID3 title of an MP3.
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if (!title) title = obj.title;
\end_layout

\begin_layout Code
    var artist = obj.meta[M_ARTIST];
\end_layout

\begin_layout Code
    if (!artist)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        artist = 'Unknown';
\end_layout

\begin_layout Code
        artist_full = null;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        artist_full = artist;
\end_layout

\begin_layout Code
        desc = artist;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
   var album = obj.meta[M_ALBUM];
\end_layout

\begin_layout Code
   if (!album)
\end_layout

\begin_layout Code
    {   
\end_layout

\begin_layout Code
        album = 'Unknown';
\end_layout

\begin_layout Code
        album_full = null;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        desc = desc + ', ' + album;
\end_layout

\begin_layout Code
        album_full = album;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if (desc)
\end_layout

\begin_layout Code
        desc = desc + ', ';
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    desc = desc + title;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    var date = obj.meta[M_DATE];
\end_layout

\begin_layout Code
    if (!date)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        date = 'Unknown';
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        date = normalizeDate(date);
\end_layout

\begin_layout Code
        desc = desc + ', ' + date;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    var genre = obj.meta[M_GENRE];
\end_layout

\begin_layout Code
    if (!genre)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        genre = 'Unknown';
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        desc = desc + ', ' + genre;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    var description = obj.meta[M_DESCRIPTION];
\end_layout

\begin_layout Code
    if (!description)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Standard
Note how we are setting properties of an object - in this case we put together
 a description and we are setting for objects that did not already have
 one.
\end_layout

\begin_layout Code
        obj.meta[M_DESCRIPTION] = desc;
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
We finally gathered all data that we need, so let's create a nice layout
 for our audio files.
 Note how we are constructing the chain, in the line below the array 'chain'
 will be converted to 'Audio/All audio' by the createContainerChain() function.
\end_layout

\begin_layout Code
    var chain = new Array('Audio', 'All audio');
\end_layout

\begin_layout Code
    obj.title = title;
\end_layout

\begin_layout Standard
The UPnP class argument to addCdsObject() is optional, if it is not supplied
 the default UPnP class will be used.
 However, it is suggested to correctly set UPnP classes of containers and
 objects - this information may be used by some renderers to identify the
 type of the container and present the content in a different manner .
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Artists', artist, 'All songs');
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'All - full name');
\end_layout

\begin_layout Code
    var temp = '';
\end_layout

\begin_layout Code
    if (artist_full)
\end_layout

\begin_layout Code
        temp = artist_full;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if (album_full)
\end_layout

\begin_layout Code
        temp = temp + ' - ' + album_full + ' - ';
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    obj.title = temp + title;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Artists', artist, 'All - full name');
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Artists', artist, album);
\end_layout

\begin_layout Code
    obj.title = track + title;
\end_layout

\begin_layout Standard
Remember, the server will sort all items by ID3 track if the container class
 is set to UPNP_CLASS_CONTAINER_MUSIC_ALBUM.
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_AL
BUM);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Albums', album);
\end_layout

\begin_layout Code
    obj.title = track + title;
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_AL
BUM);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Genres', genre);
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_GE
NRE);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    chain = new Array('Audio', 'Year', date);
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC);
 
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Subsubsection
Weborama Content Handler
\end_layout

\begin_layout Standard
Weborama content handler is really simple, the service aims at providing
 'radio on demand', so everything here maps to a search query that you specified
 in the config.xml:
\end_layout

\begin_layout Code
function addWeborama(obj)
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var req_name = obj.aux[WEBORAMA_AUXDATA_REQUEST_NAME];
\end_layout

\begin_layout Code
    if (req_name)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        var chain = new Array('Online Services', 'Weborama', req_name);
\end_layout

\begin_layout Code
        addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_PLAYLIST_CONTA
INER);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
} 
\end_layout

\begin_layout Subsubsection
Image Content Handler
\end_layout

\begin_layout Standard
This function takes care of images.
 Currently it does very little sorting, but could easily be extended - photos
 made by digital cameras provide lots of information in the Exif tag, so
 you could easily add code to sort your pictures by camera model or anything
 Exif field you might be interested in.
\end_layout

\begin_layout Description
Note: if you want to use those additional Exif fields you need to compile
 MediaTomb with libexif support and also specify the fields of interest
 in the import section of your configuration file (See documentation about
 library-options).
\end_layout

\begin_layout Code
function addImage(obj) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var chain = new Array('Photos', 'All Photos');
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    var date = obj.meta[M_DATE];
\end_layout

\begin_layout Code
    if (date)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        chain = new Array('Photos', 'Date', date);
\end_layout

\begin_layout Code
        addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Standard
Just like in the addAudio() function - we simply construct our container
 chain and add the object.
\end_layout

\begin_layout Subsubsection
Video Content Handler
\end_layout

\begin_layout Standard
Not much to say here...
 I think libextractor is capable of retrieving some information from video
 files, however I seldom encountered any video files populated with metadata.
 You could also try ffmpeg to get more information, however by default we
 keep it very simple - we just put everything into the 'All Video' container.
\end_layout

\begin_layout Code
function addVideo(obj) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var chain = new Array('Video');
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Subsubsection
YouTube Content Handler
\end_layout

\begin_layout Standard
This helper function processes items that are imported from the YouTube
 service; these items have extended properties that were described in detail
 earlier in this document.
 Let's have a look at how they are used:
\end_layout

\begin_layout Code
function addYouTube(obj)
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
   var chain;
\end_layout

\begin_layout Standard
First, we want to sort the content by average rating.
 Remember - all properties in the obj.aux array are strings, so we will do
 an extra conversion because we want to round the rating.
\end_layout

\begin_layout Code
   var temp = parseInt(obj.aux[YOUTUBE_AUXDATA_AVG_RATING], 10);
\end_layout

\begin_layout Standard
Make sure to check that we got a number.
\end_layout

\begin_layout Code
   if (temp != Number.NaN)
\end_layout

\begin_layout Code
   {
\end_layout

\begin_layout Code
       temp = Math.round(temp);
\end_layout

\begin_layout Standard
Here is the place if you want to have a different range of ratings in your
 tree structure:
\end_layout

\begin_layout Code
       if (temp > 3)
\end_layout

\begin_layout Code
       {
\end_layout

\begin_layout Code
           var chain = new Array('Online Services', 'YouTube',
\end_layout

\begin_layout Code
                                  'Rating', temp.toString());
\end_layout

\begin_layout Code
           addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
       }
\end_layout

\begin_layout Code
   }
\end_layout

\begin_layout Standard
Next, we process the request, i.e.
 - description of the request to the YouTube service that created the item.
 Some requests may contain additional information like the name of the region.
\end_layout

\begin_layout Code
    temp = obj.aux[YOUTUBE_AUXDATA_REQUEST];
\end_layout

\begin_layout Code
    if (temp)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        var subName = (obj.aux[YOUTUBE_AUXDATA_SUBREQUEST_NAME]);
\end_layout

\begin_layout Code
        var feedName = (obj.aux[YOUTUBE_AUXDATA_FEED]);
\end_layout

\begin_layout Code
        var region = (obj.aux[YOUTUBE_AUXDATA_REGION]);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
        chain = new Array('Online Services', 'YouTube', temp);
\end_layout

\begin_layout Standard
All items will go to /Online Services/YouTube/RequestName/, below we will
 do additional refinement.
 Do not forget to check if the values are valid, some requests may not have
 all of the tags set (for example - if no specific region was defined in
 the config, then the associated request will not provide the REGION auxdata)
\end_layout

\begin_layout Code
       if (subName)
\end_layout

\begin_layout Code
           chain.push(subName);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
       if (feedName)
\end_layout

\begin_layout Code
           chain.push(feedName);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
       if (region)
\end_layout

\begin_layout Code
           chain.push(region); 
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
       addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Subsubsection
Apple Trailers Content Handler
\end_layout

\begin_layout Standard
This function processes items that are importent via the Apple Trailers
 feature.
 We will organize the trailers by genre, post date and release date, additionall
y we will also add a container holding all trailers.
\end_layout

\begin_layout Code
function addTrailer(obj)
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var chain;
\end_layout

\begin_layout Standard
First we will add the item to the 'All Trailers' container, so that we get
 a nice long playlist:
\end_layout

\begin_layout Code
    chain = new Array('Online Services', 'Apple Trailers', 'All Trailers');
\end_layout

\begin_layout Code
    addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Standard
We also want to sort the trailers by genre, however we need to take some
 extra care here: the genre property here is a comma separated value list,
 so one trailer can have several matching genres that will be returned as
 one string.
 We will split that string and create individual genre containers.
\end_layout

\begin_layout Code
    var genre = obj.meta[M_GENRE];
\end_layout

\begin_layout Code
    if (genre)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Standard
A genre string "Science Fiction, Thriller" will be split to "Science Fiction"
 and "Thriller" respectively.
\end_layout

\begin_layout Code
        genres = genre.split(', ');
\end_layout

\begin_layout Code
        for (var i = 0; i < genres.length; i++)
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Code
            chain = new Array('Online Services', 'Apple Trailers', 'Genres',
\end_layout

\begin_layout Code
                              genres[i]);
\end_layout

\begin_layout Code
            addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
The release date is offered in a YYYY-MM-DD format, we won't do too much
 extra checking regading validity, however we only want to group the trailers
 by year and month:
\end_layout

\begin_layout Code
    var reldate = obj.meta[M_DATE];
\end_layout

\begin_layout Code
    if ((reldate) && (reldate.length >= 7))
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        chain = new Array('Online Services', 'Apple Trailers', 'Release
 Date',
\end_layout

\begin_layout Code
                          reldate.slice(0, 7));
\end_layout

\begin_layout Code
        addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
We also want to group the trailers by the date when they were originally
 posted, the post date is available via the aux array.
 Similar to the release date, we will cut off the day and create our containres
 in the YYYY-MM format.
\end_layout

\begin_layout Code
    var postdate = obj.aux[APPLE_TRAILERS_AUXDATA_POST_DATE];
\end_layout

\begin_layout Code
    if ((postdate) && (postdate.length >= 7))
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        chain = new Array('Online Services', 'Apple Trailers', 'Post Date',
\end_layout

\begin_layout Code
                          postdate.slice(0, 7));
\end_layout

\begin_layout Code
        addCdsObject(obj, createContainerChain(chain));
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
} 
\end_layout

\begin_layout Subsubsection
Putting it all together
\end_layout

\begin_layout Standard
This is the main part of the script, it looks at the mimetype of the original
 object and feeds the object to the appropriate content handler.
\end_layout

\begin_layout Code
if (getPlaylistType(orig.mimetype) == '')
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var arr = orig.mimetype.split('/'); 
\end_layout

\begin_layout Code
    var mime = arr[0];
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    var obj = orig;
\end_layout

\begin_layout Standard
All virtual objects are references to objects in the PC-Directory, so make
 sure to correctly set the reference ID!
\end_layout

\begin_layout Code
    obj.refID = orig.id;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if ((mime == 'audio')) 
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Standard
We support the Weborama online radio service, so we will do some extra handling
 for those items:
\end_layout

\begin_layout Code
        if (obj.onlineservice == ONLINE_SERVICE_WEBORAMA)
\end_layout

\begin_layout Code
            addWeborama(obj);
\end_layout

\begin_layout Code
        else
\end_layout

\begin_layout Code
            addAudio(obj); 
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if (mime == 'video') 
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Standard
We support the YouTube service which offers video items, so we will do an
 extra check to sort it properly:
\end_layout

\begin_layout Code
        if (obj.onlineservice == ONLINE_SERVICE_YOUTUBE)
\end_layout

\begin_layout Code
            addYouTube(obj);
\end_layout

\begin_layout Code
        else
\end_layout

\begin_layout Code
            addVideo(obj);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
    if (mime == 'image') 
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
         addImage(obj); 
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
We now also have OGG Theora recognition, so we can ensure that Vorbis 
\end_layout

\begin_layout Code
    if (orig.mimetype == 'application/ogg')
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
    if (obj.theora == 1)
\end_layout

\begin_layout Code
            addVideo(obj);
\end_layout

\begin_layout Code
        else
\end_layout

\begin_layout Code
            addAudio(obj);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Subsection
Playlist Script
\end_layout

\begin_layout Standard
The default playlist parsing script is called playlists.js, similar to the
 import script it works with a global object which is called 'playlist',
 the fields are similar to the 'orig' that is used in the import script
 with the exception of the playlistOrder field which is special to playlists.
\end_layout

\begin_layout Standard
Another big difference between playlist and import scripts is, that playlist
 scripts can add new media to the database, while import scripts only process
 already existing objects (the ones found in PC Directory) and just add
 additional virtual items.
\end_layout

\begin_layout Standard
The default playlist script implementation supports parsing of m3u and pls
 formats, but you can add support for parsing of any ASCII based playlist
 format.
\end_layout

\begin_layout Subsubsection
Adding Items
\end_layout

\begin_layout Standard
We will first look at a helper function:
\end_layout

\begin_layout Code
addPlaylistItem(location, title, playlistChain);
\end_layout

\begin_layout Standard
It is defined in playlists.js, it receives the location (path on disk or
 HTTP URL), the title and the desired position of the item in the database
 layout (remember the container chains used in the import script).
\end_layout

\begin_layout Standard
The function first decides if we are dealing with an item that represents
 a resource on the web, or if we are dealing with a local file.
 After that it populates all item fields accordingly and calls the addCdsObject(
) that was introduced earlier.
 Note, that if the object that is being added by the playlist script is
 not yet in the database, the import script will be invoked.
 Below is the complete function with some comments:
\end_layout

\begin_layout Code
function addPlaylistItem(location, title, playlistChain) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Standard
Determine if the item that we got is an URL or a local file.
\end_layout

\begin_layout Code
    if (location.match(/^.*:
\backslash
/
\backslash
//))
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        var exturl = new Object();
\end_layout

\begin_layout Standard
Setting the mimetype is crucial and tricky...
 if you get it wrong your renderer may show the item as unsupported and
 refuse to play it.
 Unfortunately most playlist formats do not provide any mimetype information.
\end_layout

\begin_layout Code
        exturl.mimetype = 'audio/mpeg';
\end_layout

\begin_layout Standard
Make sure to correctly set the object type, then populate the remaining
 fields.
\end_layout

\begin_layout Code
        exturl.objectType = OBJECT_TYPE_ITEM_EXTERNAL_URL;
\end_layout

\begin_layout Code
        exturl.location = location;
\end_layout

\begin_layout Code
        exturl.title = (title ? title : location);
\end_layout

\begin_layout Code
        exturl.protocol = 'http-get';
\end_layout

\begin_layout Code
        exturl.upnpclass = UPNP_CLASS_ITEM_MUSIC_TRACK;
\end_layout

\begin_layout Code
        exturl.description = "Song from " + playlist.title;
\end_layout

\begin_layout Standard
This is a special field which ensures that your playlist files will be displayed
 in the correct order inside a playlist container.
 It is similar to the id3 track number that is used to sort the media in
 album containers.
\end_layout

\begin_layout Code
        exturl.playlistOrder = playlistOrder++;
\end_layout

\begin_layout Standard
Your item will be added to the container named by the playlist that you
 are currently parsing.
\end_layout

\begin_layout Code
        addCdsObject(exturl, playlistChain,  UPNP_CLASS_PLAYLIST_CONTAINER);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
Here we are dealing with a local file.
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        if (location.substr(0,1) != '/')
\end_layout

\begin_layout Code
            location = playlistLocation + location;
\end_layout

\begin_layout Code
        var item  = new Object();
\end_layout

\begin_layout Code
        item.location = location;
\end_layout

\begin_layout Code
        if (title)
\end_layout

\begin_layout Code
            item.title = title;
\end_layout

\begin_layout Code
        else
\end_layout

\begin_layout Code
         {
\end_layout

\begin_layout Code
            var locationParts = location.split('/');
\end_layout

\begin_layout Code
            item.title = locationParts[locationParts.length - 1];
\end_layout

\begin_layout Code
            if (! item.title)
\end_layout

\begin_layout Code
                item.title = location;
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Code
        item.objectType = OBJECT_TYPE_ITEM;
\end_layout

\begin_layout Code
        item.playlistOrder = playlistOrder++;
\end_layout

\begin_layout Code
        addCdsObject(item, playlistChain,  UPNP_CLASS_PLAYLIST_CONTAINER);
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
} 
\end_layout

\begin_layout Subsubsection
Main Parsing
\end_layout

\begin_layout Standard
The actual parsing is done in the main part of the script.
 First, the type of the playlist is determined (based on the playlist mimetype),
 then the correct parser is chosen.
 The parsing itself is a loop, where each call to readln() returns exactly
 one line of text from the playlist.
 There is no possibility to go back, each readln() invocation will retrieve
 the next line until end of file is reached.
\end_layout

\begin_layout Standard
To keep things easy we will only list the m3u parsing here.
 Again, if you are not familiar with regular expressions, now is probably
 the time to take a closer look.
\end_layout

\begin_layout Code
...
\end_layout

\begin_layout Code
else if (type == 'm3u')
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var line;
\end_layout

\begin_layout Code
    var title = null;
\end_layout

\begin_layout Standard
Here is the do - while loop which will read the playlist line by line.
\end_layout

\begin_layout Code
    do
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Standard
Read the line:
\end_layout

\begin_layout Code
        line = readln();
\end_layout

\begin_layout Standard
Perform m3u specific parsing:
\end_layout

\begin_layout Code
        if (line.match(/^#EXTINF:(
\backslash
d+),(
\backslash
S.+)$/i))
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Code
            // duration = RegExp.$1; // currently unused
\end_layout

\begin_layout Code
            title = RegExp.$2;
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Code
        else if (! line.match(/^(#|
\backslash
s*$)/))
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Standard
Call the helper function to add the item once you gathered the data:
\end_layout

\begin_layout Code
            addPlaylistItem(line, title, playlistChain);
\end_layout

\begin_layout Code
            title = null;
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Standard
We will exit the loop when end of the playlist file is reached.
\end_layout

\begin_layout Code
    while (line);
\end_layout

\begin_layout Code
}
\end_layout

\begin_layout Code
...
\end_layout

\begin_layout Subsection
DVD Import Script
\end_layout

\begin_layout Standard
The DVD import script receives an object that represents a DVD image.
 The object provides information about the number of titles, chapters, audio
 tracks and about languages that are available in the image.
 You can not play the ISO directly (most players will not support this),
 so we weill create special virtual DVD objects, which will deliver an MPEG
 PES stream for the selected Title/Audio Track/Chapter.
\end_layout

\begin_layout Standard
The DVD import script is separated from the main script, the script that
 is shipped with the default installation is called import-dvd.js.
\end_layout

\begin_layout Standard
Let's have a closer look!
\end_layout

\begin_layout Code

\end_layout

\begin_layout Standard
The title of the DVD will be set to the file name of the ISO image, we want
 to get rid of the .iso extension:
\end_layout

\begin_layout Code
var title = dvd.title;
\end_layout

\begin_layout Code
var index = title.lastIndexOf('.'); 
\end_layout

\begin_layout Code
if (index > 1)
\end_layout

\begin_layout Code
    title = title.substring(0, index);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Standard
Since the object that we receive is the original ISO it will not have the
 correct video UPnP class, so we have to set it ourselves:
\end_layout

\begin_layout Code
dvd.upnpclass = UPNP_CLASS_ITEM_VIDEO;
\end_layout

\begin_layout Standard
Now we will get the number of titles and loop through them, creating a virtual
 structure for the chapters, languages and audio formats:
\end_layout

\begin_layout Code
var title_count = dvd.aux[DVD].titles.length;
\end_layout

\begin_layout Code
for (var t = 0; t < title_count; t++) 
\end_layout

\begin_layout Code
{
\end_layout

\begin_layout Code
    var title_name = 'Title';
\end_layout

\begin_layout Standard
Since the sorting is based on the titles we need a leading zero.
 Also note the (t + 1) part, the very first position in the array has an
 index of zero, however we want that the title count starts with one in
 the UI:
\end_layout

\begin_layout Code
    if (t < 9)
\end_layout

\begin_layout Code
        title_name = title_name + ' 0' + (t + 1);
\end_layout

\begin_layout Code
    else
\end_layout

\begin_layout Code
        title_name = title_name + ' ' + (t + 1);
\end_layout

\begin_layout Standard
Get the number of chapters and audio tracks for this title and loop through
 them:
\end_layout

\begin_layout Code
    var chapter_count = dvd.aux[DVD].titles[t].chapters.length;
\end_layout

\begin_layout Code
    var audio_track_count = dvd.aux[DVD].titles[t].audio_tracks.length;
\end_layout

\begin_layout Code
    for (var a = 0; a < audio_track_count; a++)
\end_layout

\begin_layout Code
    {
\end_layout

\begin_layout Code
        var chain;
\end_layout

\begin_layout Standard
Again, note the (a + 1) part, we want the first track in the UI to show
 as Track 01 and not Track 00:
\end_layout

\begin_layout Code
        var audio_name = ' - Audio Track ' + (a + 1);
\end_layout

\begin_layout Standard
We will create a structure, sorting the media by audio languages and formats:
\end_layout

\begin_layout Code
        var audio_language = dvd.aux[DVD].titles[t].audio_tracks[a].language;
\end_layout

\begin_layout Code
        var audio_format = dvd.aux[DVD].titles[t].audio_tracks[a].format;
\end_layout

\begin_layout Code
        if (audio_format != '')
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Code
            if (audio_language != '')
\end_layout

\begin_layout Code
                audio_name = audio_name + ' - ' + audio_language;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
            chain = new Array('Video', 'DVD', title, 'Audio Formats',
\end_layout

\begin_layout Code
                              audio_format, title_name + audio_name);
\end_layout

\begin_layout Standard
The code above was only dealing with containers, this loop will create the
 actual playable items: 
\end_layout

\begin_layout Code
            for (var c = 0; c < chapter_count; c++)
\end_layout

\begin_layout Code
            {
\end_layout

\begin_layout Code
                if (c < 9)
\end_layout

\begin_layout Code
                    dvd.title = "Chapter 0" + (c + 1);
\end_layout

\begin_layout Code
                else
\end_layout

\begin_layout Code
                    dvd.title = "Chapter " + (c + 1);
\end_layout

\begin_layout Standard
When attempted to play, the item created below will deliver the MPEG PES
 with title index t, chapter index c and audio track index a - we created
 the chain appropriately so that the audio index matches the language and
 audio format that we used in the container names:
\end_layout

\begin_layout Code
                addDVDObject(dvd, t, c, a, createContainerChain(chain));
\end_layout

\begin_layout Code
            }
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Standard
Same for the language:
\end_layout

\begin_layout Code
        if (audio_language != '')
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Code
            chain = new Array('Video', 'DVD', title, 'Languages',
\end_layout

\begin_layout Code
                              audio_language);
\end_layout

\begin_layout Code
            if (audio_format != '')
\end_layout

\begin_layout Code
                chain.push(title_name + audio_name + ' - ' + audio_format);
\end_layout

\begin_layout Code
            else
\end_layout

\begin_layout Code
                chain.push(title_name + audio_name);
\end_layout

\begin_layout Code
            for (var c = 0; c < chapter_count; c++)
\end_layout

\begin_layout Code
            {
\end_layout

\begin_layout Code
                if (c < 9)
\end_layout

\begin_layout Code
                    dvd.title = "Chapter 0" + (c + 1);
\end_layout

\begin_layout Code
                else
\end_layout

\begin_layout Code
                    dvd.title = "Chapter " + (c + 1);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
                addDVDObject(dvd, t, c, a, createContainerChain(chain));
\end_layout

\begin_layout Code
            }
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Standard
And we also want a list of titles with appropriate format and language informati
on:
\end_layout

\begin_layout Code
        chain = new Array('Video', 'DVD', title, 'Titles');
\end_layout

\begin_layout Code
        var titles = title_name + ' - Audio Track ' + (a + 1);
\end_layout

\begin_layout Code
        if (audio_format != '')
\end_layout

\begin_layout Code
            titles = titles + ' - ' + audio_format;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
        if (audio_language != '')
\end_layout

\begin_layout Code
            titles = titles + ' - ' + audio_language;
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
        chain.push(titles);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
        for (var c = 0; c < chapter_count; c++)
\end_layout

\begin_layout Code
        {
\end_layout

\begin_layout Code
            if (c < 9)
\end_layout

\begin_layout Code
                dvd.title = "Chapter 0" + (c + 1);
\end_layout

\begin_layout Code
            else
\end_layout

\begin_layout Code
                dvd.title = "Chapter " + (c + 1);
\end_layout

\begin_layout Code

\end_layout

\begin_layout Code
            addDVDObject(dvd, t, c, a, createContainerChain(chain));
\end_layout

\begin_layout Code
        }
\end_layout

\begin_layout Code
    }
\end_layout

\begin_layout Code
} 
\end_layout

\begin_layout Standard
Happy scripting!
\end_layout

\end_body
\end_document
