DAISY Consortium Logo - Link to Home Page

Authors:

Dave Gunn, DAISY Consortium Consultant (Chair)

Jelle Martijn Kok, Solutions Radio

Claudio Montalban, Vision Australia (Editor)

Fredrik Schill, Textalk (Editor)

Per Sennels, Norwegian Library of Talking Books and Braille

Takuro Shiroki, Shinano Kenshi

Copyright Notice:

All content of the DAISY Structure Guidelines is licensed for others to copy, distribute, and display only verbatim copies. No changes may be made and no derivative works based upon it.
Copyright © by the DAISY ConsortiumCreative Commons License: No Derivative Works


Table of Contents

1 Service Discovery

1.1 Introduction

Any DODP capable Service can register itself on the service discovery list. This list is maintained by the DAISY Consortium and is freely available. Every Service defines its name, url, country and other parameters.

A Reading System can use this list to give the end-user a list of Services to connect to. It is up to the Reading System to present this in a nice manner. It could first request a country or language to narrow the list.

The file is located at:

https://www.daisy.org/dodp/dodp-service-list.xml

1.2 Amending the Service Discovery System

To add or change your Service details on the Discovery file use the DAISY Contact form to request assistance, using the message category DAISY Online Delivery:

http://www.daisy.org/contact

A member of the DAISY team will then make contact directly to request your correctly formatted Service details to add to the discovery file.

2 Reading System Configuration

2.1 Introduction

The operation getUserCredentials() gives a Reading System the ability to fetch its username and password which it needs to login. For this to work the Service needs to assign a specific device (manufacturer and serial number) to a User. If that device requests the User credentials, the Service would return the username and password.

2.2 Security

Security is critical as the User credentials should not be handed out to any Reading System, only to one of the Reading Systems which are assigned by the User. For that reason the credentials will be encrypted before sending to the Reading System. Only Reading Systems which are assigned to the User will be able to decrypt the credentials. Other devices will not be able to decrypt the credentials. The method used is asymmetric encryption, where the Reading System has the private key and the Service has the public key.

2.2.1 Public keys

The public keys are distributed by the manufacturers. They are linked to the private keys which are stored inside the Reading Systems. Services can request this key via the publicKey URL as specified in the readingSystemList. This URL takes one GET/POST parameter which is the serial number for the device. If no serial number is given, the public corporate key is returned.

For example, URLs may look like this:

https://keys.domain.com/api/public-keys.php?serial=12345-67890
https://keys.domain.com/api/public-keys.php

2.2.2 Private keys

The private keys are created and owned by the manufacturer. They are not shared with anyone and should be kept secret under all circumstances.

2.2.3 Encryption

Currently the only encryption used is "PCKS#1" with "RSAES-OAEP" padding. This is an asymmetric encryption which can encrypt a fixed amount of data. The maximum amount of text depends on the size of the used key. A key of 1024 bits can encrypt up to 86 bytes, 2048 can encrypt up to 214 bytes.

2.3 Step by step

2.3.1 Step 1

The Reading System performs a getUserCredentials() request to the Service. This request holds the readingSystemAttributes, which include the manufacturer and serial number.

2.3.2 Step 2

The Service extracts the manufacturer name and serial number from the getUserCredentials() request. It looks up the manufacturer record from the centrally stored dodp-reading-system-list.xml (hint: cache these daily). The Service then requests the public key from the URL specified in this manufacturer record.

2.3.3 Step 3

The Service encrypts the username and the password with the public key. As a result the username and password are in a binary format. Both encrypted username and encrypted password should be base64 encoded so they are suitable for placement inside the XML response.

2.3.4 Step 4

The Service creates the credentials response and stores the encrypted username and password as encoding in the correct place. The response is then sent to the Reading System.

2.3.5 Step 5

The Reading System reads the username and password from the response. They are encrypted and base64 encoded. The Reading System will base64 decode the username and password. It reads the encryptionScheme to determine the encryption used. It will then try to decrypt the username and password with one of its private keys. It should first try its serial key, then its corporate key and lastly the example key.

2.3.6 Step 6

If successful, the Reading System uses this username and password to perform a logOn().

2.4 Amending the Reading System File

To add or amend your Reading System details on the Reading System List use the DAISY Contact form to request assistance, using the message category DAISY Online Delivery:

http://www.daisy.org/contact

A member of the DAISY team will then make contact directly to request your correctly formatted Reading System details to add to the file.

2.5 Examples

In these examples we use the following public/private key pair. We call this key "DAISY-example".

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXmtTTvovu9keHY//4RFoCuBmh
1UdEnDGsOef3543eABZz4lqr5QNO0ktfRg5kwheqVwZJHshYZuZzfgFOxVD8YlG4
F7kvhkNaC2M0XGM2BuQBgqrkOMB0EmhqBROP6tAQ4DLfTAm8FAo/rryrRoAejwxq
A8ZHdCZuINXTJluGcQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCXmtTTvovu9keHY//4RFoCuBmh1UdEnDGsOef3543eABZz4lqr
5QNO0ktfRg5kwheqVwZJHshYZuZzfgFOxVD8YlG4F7kvhkNaC2M0XGM2BuQBgqrk
OMB0EmhqBROP6tAQ4DLfTAm8FAo/rryrRoAejwxqA8ZHdCZuINXTJluGcQIDAQAB
AoGADGbE/CE9LyoEReX/PV7SAiDvL9bTgqBIS+9cs2HEsCFPtOESS7drItp/Aeco
LEPYTb3arMaQ2vJn7ZCkKL5pVmuzEvFXjO3vY0283U1xUdoevL/2yyHAM3l2dYbp
bvsPrWZhoa06mqcmN1d4XPKnLLrJzYOWDvlW7IXop6Y4EvECQQDJwHpY+bao5lE+
S7I3FnAzu6jUYA2VCTWDJVilX8sc/3OhONFlfAuv4gC2Yh+M4n8JhDZaKJ5q4Dbd
50jzSPJ9AkEAwF5/YneLUldjYZfpj/8dDBkSZ1qwB5kBpM0q/8UPassBVP00A3pa
4PCvxqhcsDPhnM9KX8N0D1f8fIM2vAoSBQJADW5l9sRxF591qysI60fwIlGM9M6M
OO7LBDcZRrEw6XZMMWCB+Dqg4I2wNHQl25A8mtqVb70ihsT0giNipOenVQJBALyp
cOEPQPJGhk8mf4gbuU8uH6CBjnZFFxmbpfomN9KSugGyOhrXGt3U728zm4Orvi7e
FaEJvX922Ub8IOgWMEkCQDAUHoY4SEZQPI9PpQrcJP87J4x3+8CfWni6SAWkuKUU
BsDoI6qtrBbVvkxx/wzv/i28scwKCj4enQkFbDWjPxg=
-----END RSA PRIVATE KEY-----

We will now describe the scenario where the device for a User requests the username and password. The username is "john.doe" and the password is "super-secret"

2.5.1 Example: The unencrypted response

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.daisy.org/ns/daisy-online/">
  <soapenv:Body>
    <credentials xmlns="http://www.daisy.org/ns/daisy-online/" >
      <username>john.doe</username>
      <password>super-secret</password>
    </credentials>
  </soapenv:Body>
</soapenv:Envelope>

2.5.2 Example: The encrypted response

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <credentials xmlns="http://www.daisy.org/ns/daisy-online/" encryptionScheme="RSAES-OAEP">
      <username>kxUCZwu/1o2pzuiK2VQfQG46+Rd7uwbP2+BD7nuvps7TcFk1H3JkIo3/wjINaABEK/r9lqY8uozh44PuyRvI0LcqxI2BvYKtWsI2CsU2pojOZJJmq5yYP4xoOq8Y6SdMTSAtNCWIlLhKJwaMUyi9KlnnG3nl8cDTK8uQrbPI078=</username>
      <password>C9vtkOagK3hS82W95bzvjKLSmvsV3N2vafqKp6mayPKqG+fCXRuT9d6qiAVv0LIuQN9k9idFc/nFAjYW3orEeTT7hU+iQmH1Az8UpqMHN54r0LjRaIVl8RyUKZcQpbMY4MTYGmSigZWrGe2RT4+puJDs2XCKx7AiVYJDkk3AS3Y=</password>
    </credentials>
  </soapenv:Body>
</soapenv:Envelope>

2.6 Command line encryption (Linux + openssl)

2.6.1 Private key generation

You can generate a 2048 bit RSA key with:

openssl genrsa -out private.pem 2048

WARNING: keep this key in a safe place and do not lose it.

2.6.2 Public key generation

You can extract the public key from the private key with:

openssl rsa -in private.pem -pubout > public.pem

The "public.pem" file now holds the public key. This file may be freely distributed.

2.6.3 Encrypt a password

echo -n "super-secret" | openssl rsautl -encrypt -oaep -pubin -inkey public.pem | base64 > encrypted.txt

2.6.4 Decrypt an encrypted password

cat encrypted.txt | base64 -d | openssl rsautl -decrypt -oaep -inkey private.pem

2.7 Example PHP code

The samples below should add more checks to determine if the encryption succeeds or fails. It is very important that the encryption function does this to prevent any leakage of unencrypted content. It should also be noted that the code should try to generate usable soap faults. (like "manufacturer not found", "serial not located", "encryption failed", etc). And not just throw a "500" HTTP error.

2.7.1 Example: Service (library) code

<?
/* --- LIBRARY CODE --- */
/* In this example we use the default username and password */
$username = "default";
$password = "default";

/* Get the example public key
 * NOTE: in production the Service should check the "manufacturer" field to use the correct key */
$key = openssl_pkey_get_public("file:///etc/ssl/DAISY-example.public.key");
if ($key) {
    openssl_public_encrypt($username, $username_crypted, $key, OPENSSL_PKCS1_OAEP_PADDING);
    $username_crypted = base64_encode($username_crypted);
    openssl_public_encrypt($password, $password_crypted, $key, OPENSSL_PKCS1_OAEP_PADDING);
    $password_crypted = base64_encode($password_crypted);
}
?>

2.7.2 Example: Reading System code

<?
/* --- READING SYSTEM CODE --- */
/* Perform the getUserCredentials() API call and read the encrypted and base64 encoded username and password */
$credentials = $daisy->getUserCredentials();
if ($credentials && $credentials['username'] && $credentials['password']) {
    /* We use the example key for now */
    $key = openssl_pkey_get_private("file:///etc/ssl/DAISY-example.private.key");
    if ($key) {
        $credentials['username'] = base64_decode($credentials['username']);
        openssl_private_decrypt($credentials['username'], $username, $key, OPENSSL_PKCS1_OAEP_PADDING);
        $credentials['password'] = base64_decode($credentials['password']);
        openssl_private_decrypt($credentials['password'], $password, $key, OPENSSL_PKCS1_OAEP_PADDING);
    }
}
?>

2.8 Some notes

3 Session management overview

3.1 Log on

A session starts with a successful logOn() operation. What the Reading System wants to do after that depends on the capabilities of the Reading System, however all Reading Systems should be able to present content to the User.

3.2 Content

So, the common thing to do after the logOn() operation is to perform the getContentList() operation with the parameter for content list identifier set to "bookshelf". This operation transfers information about the on-line bookshelf for the User from the Service to the Reading System as a contentList. If the Reading System has a display, it will normally present the bookshelf to the User as a list of books. If the Reading System does not offer this, it will typically have a mechanism for presenting the book titles aurally.

What the Reading System will do after the getContentList() operation depends on the type of Reading System as well as on the configuration of the Reading System.

The most likely actions are to:

  1. wait for a response from the User on which book to play or download; or to
  2. automatically start downloading books that are not already on the device.

In the first case, the Reading System will get the identifier of the required book from the contentList and will perform the getContentResources() operation for that identifier. At this point, the Reading System will offer information to the Service about what it wants to do with the content by use of the accessType parameter to the getContentResources() operation and the Service can then optimize the resources for the signaled activity.

In the second case, the Reading System will loop through the contentList and for each item check if it is already downloaded. If not, the Reading System will perform a getContentResources() operation with the proper content identifier and access type and start to download the resources offered from the Service.

When the Reading System receives the contentList from the Service, the Reading System must also check if there are locally stored books that previously have been on the contentList, but are not presented from the Service through the most updated contentList. This means the loans have expired and the Reading System must delete the resources for any such books from the device.

3.3 Bookmarks

Reading Systems may offer bookmark handling as part of the reading experience. In addition, Reading Systems can also support storage of bookmarks on to the Service if this optional feature is available at the Service.

In this case, before the Reading System actually presents a specific content to the User, it can perform the getBookmarks() operation to retrieve the set of bookmarks from the Service. This way the user experience will be that bookmarks and the last reading position for the books are maintained between reading sessions and cross devices.

For this to work properly, it is necessary that the Reading System updates the bookmarks on the Service at the end of reading sessions. This is managed with the updateBookmarks() operation.

3.4 Announcements

A Service may also offer announcements to Reading Systems through the getServiceAnnouncements() operation.

Reading Systems that supports announcements should check for new announcements at the very beginning of a Session and then present the announcements to the User through a suitable interface. After this, the Reading System should contact the Service for new announcements at regular intervals, as defined in the announcementsPullFrequency element of the serviceAttributes.

The Reading System should use the announcement's priority to decide on the appropriate timing for presenting its information to the User.

3.5 Log off

When the Reading System has finished all synchronization with the Service, the session should always be gracefully ended by the Reading System performing the logOff() operation.

4 Content Retrieval Sequence and Downloading and Streaming of Content

4.1 Introduction

When a valid session has been established, Content can be Downloaded or Streamed from the Service to the Reading System. This guidance serves to assist developers when setting up this communication.

In order to Download or Stream Content from a Service, a Reading System should perform the following:

  1. Get an updated list of the available Content items from the Service.
  2. Let the User select a Content item and an access type.
  3. Get the list of resources for the selected Content item.
  4. Perform the actual Download or begin Streaming and playback.

4.2 Content lists and the Bookshelf

The most common way for Reading Systems to synchronize the list of available Content items for the User is through the special Content list with the reserved id "bookshelf". For simplicity, we refer to this Content list as the Bookshelf during this guidance.

Understanding Content lists in general and the Bookshelf in particular is vital to be able to perform correct Content synchronization. Before explaining the steps outlined above, we therefore here first highlight the most important aspects of Content lists.

4.2.1 Content lists

A Content list is a collection of Content items which is either the result to a direct call to the operation getContentList() or the endpoint in a dynamic menu. Dynamic menues are explained in detail in other parts of the Guidance. The structure of Content lists are however the same for both cases.

The type for Content lists is contentList and it has the following attributes:

A contentList may also have a label to be presented to the User by the Reading System.

There exists one reserved id, the "bookshelf". Besides this, the Service can name identifiers for Content lists in the way it finds most appropriate.

The Service may return just a subset of the entire Content list to the Reading System, either for performance reasons on the Service or because the Reading System requested it to do so in the getContentList() call. The attributes totalItems, firstItem and lastItem communicates which subset of the total Content list a specific contentList represents.

4.2.2 Content items

Each Content item in a contentList is a contentItem element. For a complete description on all properties and attributes for contentItem, please see 7.14 in the DODP v2 specification. Here we will just highlight the most fundamental and important parts.

The following attributes are specified for a contentItem:

The id attribute holds the Content Identifier of the Content item. There are no reserved values for it.

firstAccessedDate and lastModifiedDate is an indication to the Reading System whether this is a new Content item or if it has been consumed before.

lastModifiedDate should be used by the Reading System to check if its stored resources for this Content item needs to be refreshed.

category and subCategory is a way to group Content items into an hierarchy of two levels.

If existing, the returnBy attribute informs when this Content item must be returned and removed from the Reading System and a finally hasBookmarks is a shortcut for Reading Systems that are interested in knowing if Content list items have bookmarks.

The following properties are specified for a contentItem:

The label is expected to be presented to the User by the Reading System and the sample may contain a short appetizer for it to the User.

An important and significant update in DODP v2 as compared with DODP v1 is that the metadata is available directly as a property on the contentItem. This means that no extra call is required from the Reading System to the Service just to retrieve the metadata. This is actually one of the most significant optimization improvements in DODP v2. The complete list of properties for metadata can be found in 7.31 in the DODP v2 specification.

The categoryLabel and subCategoryLabel are User friendly labels for the corresponding attributes category and subCategory.

A contentItem has one or more allowed access permissions which is set in its accessPermission property. Possible permissions are streaming, download, restricted download and automatic download. The definition of all values for accessPermission (the allowed combinations) and their descriptions can be found in 7.2 in the DODP v2 specification.

If available, lastmark holds the last known reading position.

Finally, multipleChoiceQuestion can be used in Content lists returned in dynamic menues and the multipleChoiceQuestion of the contentItem then represents the context menu for that Content item.

4.2.3 Example of a Content list

Taken from 6.4.1 in the DODP v2 specification, here is an example of a rather full Content list:

<contentList xmlns="http://www.daisy.org/ns/daisy-online/" id="cl123" totalItems="2">
  <label xml:lang="en">
    <text>Please select from these publications.</text>
    <audio uri="http://example.com/static/PleaseChooseFrom.mp3" size="12342"/>
  </label>
  <contentItem id="com-example-001" category="BOOK" lastModifiedDate="2015-02-25T09:20:10Z">
    <label xml:lang="en">
      <text>Harry Potter and the Chamber of Secrets</text>
      <audio uri="http://example.com/content/titles/hp_cs.mp3" size="130821"/>
    </label>
    <sample id="hp_cos-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>Harry Potter and the Chamber of Secrets</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Harry ignores warnings not to return to Hogwarts, only to find the school plagued by a series of mysterious attacks and a strange voice haunting him.</dc:description>
      <narrator>Mary Svensson</narrator>
      <size>8119213</size>
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
  </contentItem>
  <contentItem id="com-example-002" category="BOOK" lastModifiedDate="2015-02-26T13:20:10+06:00">
    <label xml:lang="en">
      <text>Harry Potter and the Goblet of Fire</text>
      <audio uri="http://example.com/content/titles/hp_gf.mp3" size="130821"/>
    </label>
    <sample id="hp_cos-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>Harry Potter and the Goblet of Fire</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Harry ignores warnings not to return to Hogwarts, only to find the school plagued by a series of mysterious attacks and a strange voice haunting him.</dc:description>
      <narrator>Mary Svensson</narrator>
      <size>8119213</size>
      <meta name="pdtb2:specVersion" content="2005-1" />    
      <meta name="cover" content="http://example.com/image.png" />
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
    <multipleChoiceQuestion id="contentId_cl123">
      <label>
        <text>What would you like to do now?</text>
      </label>
      <choices>
        <choice id="loanItem">
          <label>
            <text>Loan Book</text>
          </label>
        </choice>
        <choice id="addToWishList">
          <label>
            <text>Add to Wish List</text>
          </label>
        </choice>
      </choices>
    </multipleChoiceQuestion>
  </contentItem>
</contentList>

4.3 Get an updated list of the available Content items from the Service

Reading Systems are expected to keep a local cache of the Bookshelf in order to be able to present it to the User when the Reading System is off-line.

The latest version of the complete Bookshelf is requested by the Reading System by making the call getContentList("bookshelf", 0, -1).

Once received, the Reading System should inspect and compare the new Bookshelf with the previous, cached, version. There are a few key aspects for the Reading System to pay extra attention to:

4.4 Let the User select Content item and access type

The next step is for the Reading System to present the Bookshelf in a way so the User can get a good overview of the available Content items. The access permissions for each Content item should reflect which access types are available to the user for that Content item.

For example, when a Content item is available for both streaming and download, the User should have the possibility to choose which method to use.

4.5 Get the list of resources for a Content item

Once the user has made its selection, the Reading System needs to request information on the resources for the Content item from the Service unless the resources are already known to the Reading System due to an earlier access to that Content item.

To request the resources, the Reading System calls the operation getContentResources() with the Content Identifier and the access type as the parameters.

Valid values for the access type are:

An important note to make here is that if the access type changes (for example from DOWNLOAD to STREAM) the Reading System must issue a new call to getContentResources() since the resources may differ based on access type.

4.5.1 Resources

The result from the call to getContentResources() has the type resources, which has a single attribute lastModifiedDate, which should reflect the last modified resource and should match the corresponding value in the contentItem.

The resources has one or more resource sub elements.

The following attributes are specified for a resource:

The resource type has both a uri and a localURI attribute. localURI is a local name for the Reading System to use to reference the resource, while uri is the location of the resource's data. This system lets a Service provide resources with arbitrary URIs (such as those served by a script), while allowing Reading Systems to follow internal links in a Content item, such as in a DAISY DTB. The localURI path is relative to the root path of the Content item.

A Reading System should not use the uri attribute to name resources locally, as the URIs may resolve to scripts or other content delivery mechanisms.

Reading Systems may use the MIME type information in the mimeType attribute of a resource to order the transfer of resources. For example, a Streaming Reading System may retrieve the OPF, NCX and SMIL files of a DAISY Digital Talking Book to provide the User full navigation before downloading any audio data.

The size attribute contains the size of the resource in bytes and the lastModifiedDate indicates when this specific resource was last updated at the Service.

Finally, serverSideHash is an optional server side hash of the resource.

The Service may freely choose which algorithm to use for calculating the serverSideHash. It is required for the serverSideHash to remain constant while the resource is unchanged and the same algorithm must be used for calculating the serverSideHash for all resources.

By examining the localURI, the lastModifiedDate and the serverSideHash attributes of resources combined, Reading Systems can identify duplicate resources for a Content item, provided by multiple calls to getContentResources(), with various methodHint parameters provided.

4.5.2 Packages

The resources may also have zero or more package sub elements.

The package element contains 1 or more resourceRef sub elements. For the resourceRef sub elements, the localURI should match the localURI of a resource, indicating that the matched resource can be found in the package.

The following attributes are specified for a package:

The uri attribute contains the URI of a package in which the resource can be found.

The value of this attribute refers to a URI, which the Reading System may choose to download instead of the uri attribute of the individual resources.

The Service thus has the possibility to group one or more resources into one package, such as all text resources of an audio book.

The mimeType attribute indicates to the Reading System how to unpack the package.

The size attribute contains the size of the package in bytes and the lastModifiedDate indicates when this package was last updated at the Service.

4.5.3 Example of resources

Taken from 6.12.1 in the DODP v2 specification, here is an example of a resources instance where a few resources can also be downloaded as part of a package.

<resources xmlns="http://www.daisy.org/ns/daisy-online/" lastModifiedDate="2015-02-26T13:20:10+06:00" >
  <resource mimeType="text/xml" size="123456" uri="https://example.com/content/get.php?a123891" localURI="package.opf" lastModifiedDate="2015-02-26T13:20:10+06:00" />
  <resource mimeType="application/x-dtbncx+xml" size="123456" uri="https://example.com/content/get.php?a123892" localURI="nav.ncx" lastModifiedDate="2015-02-25T09:20:10Z" />
  <resource mimeType="application/smil" size="567890" uri="https://example.com/content/get.php?a123893" localURI="chapter_1.smil" lastModifiedDate="2015-02-25T09:20:10Z" />
  <resource mimeType="audio/mpeg" size="123456789" uri="https://example.com/content/get.php?a123894" localURI="chapter_1.mp3" lastModifiedDate="2015-02-25T09:20:10Z" />
  <package mimeType="application/zip" size="987" uri="https://example.com/content/get.php?123" lastModifiedDate="2015-02-26T13:20:10+06:00">
    <resourceRef localURI="package.opf" />
    <resourceRef localURI="nav.ncx" />
    <resourceRef localURI="chapter_1.smil" />
  </package>
</resources>

4.6 Perform Download or begin Streaming and playback

When a Reading System attempts to Stream DAISY content, it should ensure files are retrieved in a logical order to prevent excessive calls and load on Services for retrieving non required files. For example the Reading System will access the NCC or NCX files, and by interrogating their contents determine the files that are needed to begin Streaming. This ensures that retrieving all resources is not required to begin Streaming.

A Reading System may wish to perform Automatic Download. It may do so by providing either DOWNLOAD_ONLY, STREAM_AND_DOWNLOAD, STREAM_AND_RESTRICTED_DOWNLOAD or RESTRICTED_DOWNLOAD_ONLY as the value for the accessConfig in the readingSystemAttributes.

Then any contentItem returned from the Service having its accessPermission set to either DOWNLOAD_ONLY_AUTOMATIC_ALLOWED, STREAM_AND_DOWNLOAD_AUTOMATIC_ALLOWED, STREAM_AND_RESTRICTED_DOWNLOAD_AUTOMATIC_ALLOWED or RESTRICTED_DOWNLOAD_ONLY_AUTOMATIC_ALLOWED is available for Automatic Download.

If the property progressStateOperationAllowed in the serviceAttributes is set to true, the Reading System may call the operation setProgressState() to indicate the state in which a current Streaming or Download operation for a Content item is in. The parameters to setProgressState() are contentID and state.

Allowed values for the state parameter are:

5 Service Announcements

5.1 Introduction

DODP2 provides support for sending short messages in text and/or audio form to inform Users of events. These could include informing the User about new titles available, overdue notices, or important messages such as server maintenance announcements.

DODP2 is a "Pull" protocol. Therefore it is not recommended for sending time critical messages (such as emergency announcements) as it is dependent on the Reading System to poll the Service and Pull the announcement based on a set "Pull Frequency".

The Service Announcements Operation is optional. A server may choose not to implement the Operation, however its implementation is recommended as it allows efficient communication to Users via Reading Systems that support the Operation. It is a requirement that Reading Systems support this Operation.

5.2 Enabling Support for Service Announcements

A Service supporting Announcements must inform the Reading System by including in serviceAttributes, an Operation element with the value of SERVICE_ANNOUNCEMENTS.

Equally, a Service can indicate it does not support Announcements by not including the SERVICE_ANNOUNCEMENTS value.

If a Service does not support Service Announcements, the Service must return an operationNotSupported Fault when a Reading System calls getServiceAnnouncements().

5.2.1 Example: Service Attributes for a Service supporting Service Announcements

<serviceAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <serviceProvider id="gy-zenith" />
  <service id="gy-zenith-libraryServiceDeluxe" />
  <supportsServerSideBack>true</supportsServerSideBack>
  <supportsSearch>true</supportsSearch>
  <supportedUplinkAudioCodecs>
    <codec>audio/mpeg</codec>
  </supportedUplinkAudioCodecs>
  <supportsAudioLabels>true</supportsAudioLabels>
  <supportedOptionalOperations>
    <operation>DYNAMIC_MENUS</operation>
    <operation>SET_BOOKMARKS</operation>
    <operation>GET_BOOKMARKS</operation>
    <operation>SERVICE_ANNOUNCEMENTS</operation>
    <operation>PDTB2_KEY_PROVISION</operation>
  </supportedOptionalOperations>
  <accessConfig>STREAM_AND_RESTRICTED_DOWNLOAD</accessConfig>
  <announcementsPullFrequency>120</announcementsPullFrequency>
  <progressStateOperationAllowed>true</progressStateOperationAllowed>
</serviceAttributes>

5.3 Announcements Pull Frequency

The announcementPullFrequency value found in the serviceAttributes informs the Reading System how often to pull Announcements from the Service. A Service may choose to enter a value of "0", in which case the Reading System should only pull Announcements after logOn(). The value is specified in minutes.

Services should consider the value of the announcementPullFrequency. It is recommended not to make this value too frequent unless delivery of urgent messages is of paramount importance as this could lead to performance issues due to constant polling of the server as well as increased data traffic for the User. This is especially relevant for Reading Systems in mobile networks.

5.3.1 Example: serviceAttributes for a Service with announcementPullFrequency of 2 hours (120 minutes)

<serviceAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <serviceProvider id="gy-zenith" />
  <service id="gy-zenith-libraryServiceDeluxe" />
  <supportsServerSideBack>true</supportsServerSideBack>
  <supportsSearch>true</supportsSearch>
  <supportedUplinkAudioCodecs>
    <codec>audio/mpeg</codec>
  </supportedUplinkAudioCodecs>
  <supportsAudioLabels>true</supportsAudioLabels>
  <supportedOptionalOperations>
    <operation>DYNAMIC_MENUS</operation>
    <operation>SET_BOOKMARKS</operation>
    <operation>GET_BOOKMARKS</operation>
    <operation>SERVICE_ANNOUNCEMENTS</operation>
    <operation>PDTB2_KEY_PROVISION</operation>
  </supportedOptionalOperations>
  <accessConfig>STREAM_AND_RESTRICTED_DOWNLOAD</accessConfig>
  <announcementsPullFrequency>120</announcementsPullFrequency>
  <progressStateOperationAllowed>true</progressStateOperationAllowed>
</serviceAttributes>

5.4 Reading System checking Announcements

A Reading System checks for new Announcements when connected to a Service by calling the getServiceAnnouncements() Operation.

It is recommended that Reading Systems check for Announcements immediately after completing the initialization of a new Session and re-checks every X minutes according to the announcmentPullFrequency.

A Reading System should not call the getServiceAnnouncements() Operation if the Service does not have the SERVICE_ANNOUNCEMENTS value in its serviceAttributes.

5.4.1 Example: getServiceAnnouncements SOAP call

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.daisy.org/ns/daisy-online/IDAISYOnlineService/getServiceAnnouncements</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getServiceAnnouncements xmlns="http://www.daisy.org/ns/daisy-online/" />
  </s:Body>
</s:Envelope>

5.5 Service Response

If there are no Announcements, the Service must respond with an empty Announcement list.

5.5.1 Example: Announcement

<announcements xmlns="http://www.daisy.org/ns/daisy-online/">
  <announcement id="downtime" priority="HIGH" type="SYSTEM">
    <label xml:lang="en">
      <text>The Service will not be available for 30 minutes from 1:30pm today, Friday the 10th of September due to maintenance.</text>
      <audio uri="http://example.com/content/messages/current.mp3" rangeBegin="0" rangeEnd="65856" size="65856"/>
    </label>
  </announcement>
  <announcement id="survey" priority="MEDIUM" type="INFORMATION">
    <label xml:lang="en">
      <text>A new survey is available, fill it in online at our home page, or use your Daisy Online Reading System if it has the required capabilities. Chance to win a Phantom Pocket Reader!</text>
      <audio uri="http://example.com/content/messages/current.mp3" rangeBegin="65857" size="92112"/>
    </label>
  </announcement>
</announcements>

5.5.2 Example: Empty Service Announcement SOAP response

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <ActivityId CorrelationId="683a3f7c-6787-4fe3-97b6-72d563635c7a" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">922f0811-e889-4422-8a83-83090d7ebe0e</ActivityId>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getServiceAnnouncementsResponse xmlns="http://www.daisy.org/ns/daisy-online/">
      <announcements />
    </getServiceAnnouncementsResponse>
  </s:Body>
</s:Envelope>

5.6 Announcement Attributes

Announcements may contain the following attributes. This document will refer to the example in the previous section to describe the different attributes available.

5.6.1 Announcement id

The id attribute is required and valid only for the current session. This is the identifier of the Announcement.

A Service may remove unread Announcements from the Service at any time and for any reason. To avoid potential retrieval conflicts, a Reading System must treat the Announcement ids as valid only for the duration of the active Session.

5.6.2 Announcement Type

The Announcement type indicates the kind of Announcement being sent to the Reading System. Announcement types are optional and have a default value of INFORMATION.

The possible Announcement types are:

5.6.3 Announcement Priority

The Announcement priority informs the Reading System of the immediacy with which the Announcement should be rendered. It is a required attribute with a default value of LOW.

Following are the possible Announcement priority types as well as examples of how Reading Systems may interpret the Announcement priority to render them to the User:

In all cases a Reading System must present the Announcement in a way that enables the User to re-read the Announcement.

5.6.4 Example: XML Fragment containing Announcement id, type and priority

<announcement id="downtime" priority="HIGH" type="SYSTEM">

5.7 Announcements with Audio files

Announcements may contain audio files. Services in countries where TTS doesn't correctly render their native language are advised to attach such a file.

The use of audio files is optional. When attaching audio Announcements Services should also be mindful of the load on the Service, Reading Systems, as well as bandwidth that particularly affects Users of mobile networks.

The Audio element is used to contain the URI to the audio file as well as the attributes.

5.7.1 Example: XML Fragment containing Audio Element

<announcement id="downtime" priority="HIGH" type="SYSTEM">
  <label xml:lang="en">
    <text>The Service will not be available for 30 minutes from 1:30pm today, Friday the 10th of September due to maintenance.</text>
    <audio uri="http://example.com/content/messages/current.mp3" rangeBegin="0" rangeEnd="65856" size="65856"/>
  </label>
</announcement>

5.8 Attributes of the Audio element

The Audio element may contain the following attributes. This document will refer to the example in the previous section to describe the different attributes available.

5.8.1 Audio uri

This is the URI of the audio file containing the Announcement the Reading System should render to the User. This attribute is required..

5.8.2 Audio rangeBegin

The Audio rangeBegin attribute is the byte offset of the start of the audio resource named in the uri attribute. If the rangeBegin attribute is not present, the start offset is 0. This attribute is optional.

5.8.3 Audio rangeEnd

The Audio rangeEnd attribute is the byte offset of the end of the audio resource named in the uri attribute. If the rangeEnd attribute is not present, the end is the last byte of the resource. This attribute is optional.

5.8.4 Audio size

The Audio size attribute is the size in bytes of the audio resource named in the uri attribute.

5.9 Mark Announcement as read

After rendering Announcements to a User, a Reading System may call the markAnnouncementsAsRead() Operation to inform the Service the Announcement has been read and should not be sent again on the next getServiceAnnouncements() call.

A Reading System could choose to present the option to the User to mark an Announcement as read via the UI and immediately delete the Announcement from the Reading System. In this case the Reading System should make it clear to the User the Announcement is being deleted.

Equally a Reading System could choose to mark the Announcement as read after it's rendered and present the User the option to delete it via the UI, if choosing this option the Reading System should be responsible for caching the Announcement.

To prevent conflicts arising from Announcements that have been removed from the Service, a Reading System must only pass identifier values obtained from the last call to getServiceAnnouncements() during the active Session to markAnnouncementsAsRead().

A Reading System may mark more than one Announcement as read in the same call to markAnnouncementsAsRead(). If an invalidParameter Fault is returned, the Reading System must call markAnnouncementsAsRead() sequentially for each Announcement to determine which identifier caused the Fault.

The markAnnouncementsAsRead Operation contains the read parameter and the item element.

The Service response will be a boolean where true means the Announcement was successfully marked as read, otherwise the Service must return a Fault. The Service must not return false.

The Service must return true if the Announcement was previously returned in the current session.

5.9.1 Example: Announcement list showing 2 Announcements

<announcements>
  <announcement id="891" priority="HIGH">
    <label xml:lang="en">
      <text>Test Announcement 1</text>
    </label>
  </announcement>
  <announcement id="892" priority="HIGH">
    <label xml:lang="en">
      <text>Test Announcement 2</text>
    </label>
  </announcement>
</announcements>

5.9.2 Example: SOAP call to markAnnouncementsAsRead

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.daisy.org/ns/daisy-online/IDAISYOnlineService/markAnnouncementsAsRead</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <markAnnouncementsAsRead xmlns="http://www.daisy.org/ns/daisy-online/">
      <read>
        <item>891</item>
      </read>
    </markAnnouncementsAsRead>
  </s:Body>
</s:Envelope>

5.9.3 Example: Service SOAP Response

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <ActivityId CorrelationId="330549e6-c2a3-4347-b21a-5aa02ab34c7b" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">2ed3db37-06c3-4b08-85f5-148991ca160c</ActivityId>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <markAnnouncementsAsReadResponse xmlns="http://www.daisy.org/ns/daisy-online/">
      <markAnnouncementsAsReadResult>true</markAnnouncementsAsReadResult>
    </markAnnouncementsAsReadResponse>
  </s:Body>
</s:Envelope>

5.9.4 Example: Announcement xml fragment response to getServiceAnnouncements after markAnnouncementsAsRead

<announcements>
  <announcement id="892" priority="HIGH">
    <label xml:lang="en">
      <text>Test Announcement 2</text>
    </label>
  </announcement>
</announcements>

6 Bookmarks

6.1 Introduction

DODP2 provides Operations to support the storage of bookmarks, highlights and last marks (last reading position on the title) on the Service, which allows Users to synchronize these across multiple devices.

Bookmarks, highlights and last marks are contained in an xml fragment referred to as bookmarkSet. The bookmarks grammar used in the protocol is defined by the Portable Bookmarks and Highlights section of the DAISY 3, Release 2005 ANSI/NISO Z39.86-2005 specification.

Reading Systems may store bookmark sets in a Service that supports them by the updateBookmarks() operation; Reading Systems can retrieve stored bookmarks with the getBookmarks() Operation. Services can also predefine bookmarks for the User to access.

The bookmarks Operations are optional. A Service may wish not to implement the Operations, however their implementation is recommended as it allows Users with multiple devices to preserve their bookmark set, enabling them to for example continue reading a book on a different device from the last reading position. It is a requirement that Reading Systems support this Operation.

6.2 Enabling Support for Bookmark Operations

A Service may support the retrieval of bookmark sets or both the setting and retrieval of bookmark sets.

A Service supporting setting of bookmark sets must inform the Reading System by including an Operation element with the value of SET_BOOKMARKS in its serviceAttributes as a response to logOn(), a Service supporting the retrieval of bookmark sets must include the GET_BOOKMARKS value in its response.

Equally, a Service can indicate it does not support one or both Operations by not including the SET_BOOKMARKS and or GET_BOOKMARKS values.

If a Service does not support bookmark Operations, the Service must return an operationNotSupported Fault when a Reading System calls getBookmarks() or updateBookmarks().

6.2.1 Example: Service Attributes for a Service supporting both bookmark Operations.

<serviceAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <serviceProvider id="gy-zenith" />
  <service id="gy-zenith-libraryServiceDeluxe" />
  <supportsServerSideBack>true</supportsServerSideBack>
  <supportsSearch>true</supportsSearch>
  <supportedUplinkAudioCodecs>
    <codec>audio/mpeg</codec>
  </supportedUplinkAudioCodecs>
  <supportsAudioLabels>true</supportsAudioLabels>
  <supportedOptionalOperations>
    <operation>DYNAMIC_MENUS</operation>
    <operation>SET_BOOKMARKS</operation>
    <operation>GET_BOOKMARKS</operation>
    <operation>SERVICE_ANNOUNCEMENTS</operation>
    <operation>PDTB2_KEY_PROVISION</operation>
  </supportedOptionalOperations>
  <accessConfig>STREAM_AND_RESTRICTED_DOWNLOAD</accessConfig>
  <announcementsPullFrequency>120</announcementsPullFrequency>
  <progressStateOperationAllowed>true</progressStateOperationAllowed>
</serviceAttributes>

6.3 The bookmarkObject

The bookmarkObject contains the bookmarkSet, in addition is has an optional attribute with the last modified date and time zone, these attribute enables support for multiple devices setting bookmarks.

When a Reading System receives a bookmark set that is older than its internal bookmark set, it should update the Service bookmark set with its internal copy, where a Reading System receiving a newer bookmark set should update its internal bookmark set with the one received from the Service.

The additional information is also important for supporting setting bookmarks in offline mode, for this reason a Reading System should always update and not entirely replace its internal bookmark set with the bookmark set received from the Service.

6.4 The bookmarkSet

The bookmarkSet is described in the Portable Bookmarks and Highlights section of the DAISY 3, Release 2005 ANSI/NISO Z39.86-2005 specification.

A bookmarkSet may contain one or more bookmarks, highlights and a last mark.

Bookmark sets contain different elements depending on the type of Content Item they refer to, for instance Audio only Items will express a bookmark based on the time offset for the point referenced to a SMIL, while a Text only Item will express it in a character offset. Text and Audio Items will contain both.

6.4.1 Example: Bookmark Set containing examples of all types of Bookmarks on an Audio Only Item

<bookmarkSet xmlns="http://www.daisy.org/z3986/2005/bookmark/">
   <title>
     <text>Gone with the Wind</text>
     <audio src="gwtw_title.mp3" />
   </title>
   <uid>us-rfbd-JT065</uid>
   <lastmark>
     <ncxRef>gwtw.ncx#lvl1_5</ncxRef>
     <URI>gwtw_ch5.smil#para023</URI>
     <timeOffset>03:52.00</timeOffset>
   </lastmark>
   <bookmark>
     <ncxRef>gwtw.ncx#lvl1_1</ncxRef>
     <URI>gwtw_ch1.smil#para008</URI>
     <timeOffset>00:22.00</timeOffset>
   </bookmark>
   <bookmark>
     <ncxRef>gwtw.ncx#lvl1_3</ncxRef>
     <URI>gwtw_ch3.smil#para012</URI>
     <timeOffset>01:28.00</timeOffset>
     <note>
       <text>Atlanta burns.</text>
     </note>
   </bookmark>
   <hilite>
     <hiliteStart>
       <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
       <URI>gwtw_ch4.smil#para001</URI>
       <timeOffset>00:00.00</timeOffset>
     </hiliteStart>
     <hiliteEnd>
       <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
       <URI>gwtw_ch4.smil#para006</URI>
       <timeOffset>04:06.00</timeOffset>
     </hiliteEnd>
   </hilite>
</bookmarkSet>

6.4.2 Example: Bookmark Set containing a lastmark on a Text Only Item

<bookmarkSet xmlns="http://www.daisy.org/z3986/2005/bookmark/">
   <title>
      <text>Chemistry Today</text>
   </title>
   <uid>uk-rnib-MM499</uid>
   <lastmark>
      <ncxRef>chemtd.ncx#lvl1_3</ncxRef>
      <URI>chemtd.smil#para297</URI>
      <charOffset>130</charOffset>
   </lastmark>
</bookmarkSet>

6.4.3 Example: Bookmark Set containing a lastmark on a Text and Audio Item

<bookmarkSet  xmlns="http://www.daisy.org/z3986/2005/bookmark/">
   <title>
      <text>Physics Yesterday</text>
   </title>
   <uid>uk-rnib-MM498</uid>
   <lastmark>
     <ncxRef>physyd.ncx#lvl1_5</ncxRef>
     <URI>physyd.smil#para_573</URI>
     <timeOffset>02:01.00</timeOffset>
     <charOffset>250</charOffset>
   </lastmark>
</bookmarkSet>

6.5 Bookmark Set Elements

A bookmarkSet may contain the following elements. This document will refer to the example in the previous section to describe the different elements available.

6.5.1 title

Contains the title, in text and in an optional audio clip, of the Content Item for which the bookmark set was created.

6.5.1.1 Example: XML Fragment containing title

<title>
  <text>Gone with the Wind</text>
  <audio src="gwtw_title.mp3" />
</title>

6.5.2 text

Text of the Title

6.5.2.1 Example: XML Fragment containing title text

<title>
  <text>Gone with the Wind</text>
  <audio src="gwtw_title.mp3" />
</title>

6.5.3 audio

The audio clip for title of the Content Item, specified in any format supported.

6.5.3.1 Attributes

src (%URI, #REQUIRED): The src attribute holds the URI of the audio file that contains the referenced clip.

clipBegin (%SMILtimeVal, IMPLIED): The clipBegin attribute specifies the beginning of a segment of a continuous media object as a time offset from the start of the media object. The value syntax is defined by the SMIL 2.0 Timing and Synchronization Module [SMIL].

clipEnd (%SMILtimeVal, IMPLIED): The clipEnd attribute specifies the end of a segment of a continuous media object as a time offset from the start of the media object. It uses the same attribute value syntax as clipBegin.

6.5.3.2 Example: XML Fragment containing audio text

<title>
  <text>Gone with the Wind</text>
  <audio src="gwtw_title.mp3" />
</title>

6.5.4 uid

The globally unique identifier for the book, drawn from the package file. Matches the dc:Identifier referenced by the unique-identifier attribute on the package file's package element.

6.5.4.1 Example: XML Fragment containing title uid

<uid>us-rfbd-JT065</uid>

6.5.5 lastmark

Location where User most recently ceased reading and where player will resume play when restarted. Location consists of a URI pointing to the id attribute of the par or seq element in the SMIL file that contains the lastmark, plus a time offset and/or character offset to the exact point.

6.5.5.1 Example: XML Fragment containing title lastmark

<lastmark>
  <ncxRef>gwtw.ncx#lvl1_5</ncxRef>
  <URI>gwtw_ch5.smil#para023</URI>
  <timeOffset>03:52.00</timeOffset>
</lastmark>

6.5.6 ncxRef

Captures current location in NCX (the id of the current navPoint) at time lastmark, bookmark, or highlight is set. Ensures that current location in NCX and SMIL are synchronized after moving to a lastmark, bookmark, or highlight so that any global navigation commands issued by the User will start from the current location.

6.5.6.1 Example: XML Fragment containing the ncxRef

<lastmark>
  <ncxRef>gwtw.ncx#lvl1_5</ncxRef>
  <URI>gwtw_ch5.smil#para023</URI>
  <timeOffset>03:52.00</timeOffset>
</lastmark>

6.5.7 URI

Pointer to id of par or seq in SMIL that contains the lastmark, bookmark, hiliteStart, or hiliteEnd.

6.5.7.1 Example: XML Fragment containing the URI

<lastmark>
  <ncxRef>gwtw.ncx#lvl1_5</ncxRef>
  <URI>gwtw_ch5.smil#para023</URI>
  <timeOffset>03:52.00</timeOffset>
</lastmark>

6.5.8 timeOffset

Exact position of lastmark, bookmark, hiliteStart, or hiliteEnd in the sequential audio presentation; a non-negative clock value, relative to the start of the SMIL time container referenced in the URI.

6.5.8.1 Example: XML Fragment containing the time offset

<lastmark>
  <ncxRef>gwtw.ncx#lvl1_5</ncxRef>
  <URI>gwtw_ch5.smil#para023</URI>
  <timeOffset>03:52.00</timeOffset>
</lastmark>

6.5.9 charOffset

Exact position of bookmark, lastmark, hiliteStart, or hiliteEnd in textual content file referenced (via SMIL) by the URI.

6.5.9.1 Example: XML Fragment containing the char offset

<lastmark>
   <ncxRef>chemtd.ncx#lvl1_3</ncxRef>
   <URI>chemtd.smil#para297</URI>
   <charOffset>130</charOffset>
</lastmark>

6.5.10 bookmark

Point in document marked by User for direct access in future. Bookmark consists of location and optional note. Location consists of a URI pointing to the id attribute of the par or seq element in the SMIL file that contains the bookmark, plus a time offset and/or character offset to the exact point.

6.5.10.1 Attributes

label (CDATA, #IMPLIED): optional attribute for use in storing identifying label to assist User in choosing among a set of bookmarks.

xml:lang (%languagecode, #IMPLIED): optional attribute for use in identifying the language of label and note for this bookmark, using an [RFC 3066] language code.

6.5.10.2 Example: XML Fragment containing a Bookmark

<bookmark>
  <ncxRef>gwtw.ncx#lvl1_1</ncxRef>
  <URI>gwtw_ch1.smil#para008</URI>
  <timeOffset>00:22.00</timeOffset>
</bookmark>

6.5.11 hilite

A block of text marked by the User with an optional note attached.

6.5.11.1 Attributes

label (CDATA, #IMPLIED): optional attribute for use in storing identifying label to assist User in choosing among a set of highlights.

6.5.11.2 Example: XML Fragment containing a Highlight

<hilite>
  <hiliteStart>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para001</URI>
    <timeOffset>00:00.00</timeOffset>
  </hiliteStart>
  <hiliteEnd>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para006</URI>
    <timeOffset>04:06.00</timeOffset>
  </hiliteEnd>
</hilite>

6.5.12 hiliteStart

The starting point of highlighted block. Location consists of a URI pointing to the id attribute of the par or seq element in the SMIL file that contains the beginning of the highlighted section, plus a time offset and/or character offset to the exact point.

6.5.12.1 Example: XML Fragment containing a Highlight Start

<hilite>
  <hiliteStart>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para001</URI>
    <timeOffset>00:00.00</timeOffset>
  </hiliteStart>
  <hiliteEnd>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para006</URI>
    <timeOffset>04:06.00</timeOffset>
  </hiliteEnd>
</hilite>

6.5.13 hiliteEnd

End of highlighted block. Location consists of a URI pointing to the id attribute of the par or seq element in the SMIL file that contains the end of the highlighted section, plus a time offset and/or character offset to the exact point.

6.5.13.1 Example: XML Fragment containing a Highlight End

<hilite>
  <hiliteStart>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para001</URI>
    <timeOffset>00:00.00</timeOffset>
  </hiliteStart>
  <hiliteEnd>
    <ncxRef>gwtw.ncx#lvl1_4</ncxRef>
    <URI>gwtw_ch4.smil#para006</URI>
    <timeOffset>04:06.00</timeOffset>
  </hiliteEnd>
</hilite>

6.6 Reading System calling on getBookmarks

A Reading System can retrieve a bookmark set using the getBookmarks() Operation.

The actions that can be performed by getBookmarks() are:

6.6.1 Example: SOAP call getBookmarks

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.daisy.org/ns/daisy-online/IDAISYOnlineService/getBookmarks</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getBookmarks xmlns="http://www.daisy.org/ns/daisy-online/">
      <contentID>49219</contentID>
      <action>ALL</action>
    </getBookmarks>
  </s:Body>
</s:Envelope>

6.7 Service Response to getBookmarks

The Service will return a bookmarkSet.

6.7.1 Example: SOAP Response to getBookmarks call

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <ActivityId CorrelationId="4920da1a-07ee-4d8b-a5c1-1a6c71bc6935" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">a77bc6a6-b095-4e98-8a06-3722f060c989</ActivityId>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getBookmarksResponse xmlns="http://www.daisy.org/ns/daisy-online/">
      <bookmarkObject>
        <bookmarkSet xmlns="http://www.daisy.org/z3986/2005/bookmark/">
          <title>
            <text>Bookmark List</text>
          </title>
          <hilite>
            <hiliteStart>
              <ncxRef>TestNCX</ncxRef>
              <URI>TestURI</URI>
              <timeOffset>1.x.10</timeOffset>
            </hiliteStart>
            <hiliteEnd>
              <ncxRef>TestNCX</ncxRef>
              <URI>TestURI</URI>
              <timeOffset>1.x.20</timeOffset>
            </hiliteEnd>
            <note />
          </hilite>
          <bookmark>
            <ncxRef>TestNCX</ncxRef>
            <URI>TestURI</URI>
            <timeOffset>1.x.10</timeOffset>
            <note />
          </bookmark>
        </bookmarkSet>
      </bookmarkObject>
    </getBookmarksResponse>
  </s:Body>
</s:Envelope>

6.8 Reading System Setting a Bookmark Object

A Reading System can set, update or delete elements of a bookmark set using the updateBookmarks() Operation.

The actions that can be performed by updateBookmarks() are:

A Reading System should only use REPLACE_ALL when the internal Bookmark Set has recently been updated to ensure it does not miss potential updates to the bookmark set made by other Reading Systems on the same Content Item.

The REMOVE function can be used to remove individual marks without having to pass the entire bookmark set; typically this would be used when the User manually removes a bookmark from the active Content Item.

6.8.1 Example: updateBookmarks SOAP call REPLACE_ALL

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.daisy.org/ns/daisy-online/IDAISYOnlineService/updateBookmarks</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <updateBookmarks xmlns="http://www.daisy.org/ns/daisy-online/">
      <contentID>49219</contentID>
      <action>REPLACE_ALL</action>
      <bookmarkObject>
        <bookmarkSet xmlns="http://www.daisy.org/z3986/2005/bookmark/">
          <title>
            <text>Sample Bookmark Set</text>
          </title>
          <lastmark>
            <ncxRef>TestNCX</ncxRef>
            <URI>TestURI</URI>
          </lastmark>
          <bookmark>
            <ncxRef>TestNCX</ncxRef>
            <URI>TestURI</URI>
            <timeOffset>1.x.10</timeOffset>
          </bookmark>
          <hilite>
            <hiliteStart>
              <ncxRef>TestNCX</ncxRef>
              <URI>TestURI</URI>
              <timeOffset>1.x.10</timeOffset>
            </hiliteStart>
            <hiliteEnd>
              <ncxRef>TestNCX</ncxRef>
              <URI>TestURI</URI>
              <timeOffset>1.x.20</timeOffset>
            </hiliteEnd>
          </hilite>
        </bookmarkSet>
      </bookmarkObject>
    </updateBookmarks>
  </s:Body>
</s:Envelope>

6.9 Service Response to Setting a Bookmark Object

The Service will return a boolean response to indicate if it has successfully updated the bookmark set.

6.9.1 Example: SOAP Response to updateBookmarks call

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <ActivityId CorrelationId="61811e1f-28fc-421e-90c5-ae6ad3297348" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">cd82c796-427a-4f37-98f1-87c860580761</ActivityId>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <updateBookmarksResponse xmlns="http://www.daisy.org/ns/daisy-online/">
      <updateBookmarksResult>true</updateBookmarksResult>
    </updateBookmarksResponse>
  </s:Body>
</s:Envelope>

7 Dynamic Menus

7.1 Introduction

Dynamic menus provide support for custom menus defined by the Service that can be rendered by the Reading System for such purposes as search, configuration and any other menu structure required by a library service.

This document provides guidance on how to use the DAISY online dynamic menu system. By working through the included examples you will gain an understanding of how to define dynamic menus including the associated interaction between the Reading System and Service.

This document covers not only the internals of the dynamic menu system, but also session initialization and the content item acquisition steps resulting from a book search menu.

7.2 Overview of dynamic menus

Usage of dynamic menu is separated into three typical stages.

  1. Log on
    During the logOn operation, the Service and the Reading System exchange information about the capabilities of each. The Reading System informs the Service what kind of dynamic menus are supported by the Reading System and the Service informs the Reading System if the Service supports dynamic menus or not.

  2. getQuestions
    The getQuestions operation is used by a Reading System to retrieve the choices or questions from the Service to be rendered to the User. Note that dynamc menus support both input fields and choice fields, i.e. a dynamic menu can capture data from the User (such as a data entry form) or simply act like a menu using the choice type. A response to a given dynamic menu can then be passed to getQuestions again where the Service, based on this response, may respond with another dynamic menu to be rendered resulting in support for hierarchic menus.

  3. Actions as the result of menu choices
    The menus may support many levels but eventually this will lead to either a contentList or label end point. This represents the result of the menu selection. For example, the label may contain a message such as "the book has been added to the bookshelf" or "user configuration updated successfully".

7.3 Log on

7.3.1 readingSystemAttributes

Reading Systems must inform the DAISY Online Service about its user interface capabilities using the following switches.

7.3.1.1 Example: readingSystemAttributes

<readingSystemAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <manufacturer>ACME Corporation</manufacturer>
  <model>Pro Phantom III</model>
  <serialNumber>64321</serialNumber>
  <version>1.23</version>
  <config>
    <accessConfig>STREAM_ONLY</accessConfig >
    <supportsMultipleSelections>false</supportsMultipleSelections>
    <supportsAdvancedDynamicMenus>false</supportsAdvancedDynamicMenus>
    <preferredUILanguage>en</preferredUILanguage>
    <supportedContentFormats>
      <contentFormat>ANSI/NISO Z39.86-2005</contentFormat>
      <contentFormat>Daisy 2.02</contentFormat>
    </supportedContentFormats>
    <supportedContentProtectionFormats />
    <supportedMimeTypes>
      <mimeType type="text/plain" xml:lang="en"/>
      <mimeType type="audio/mpeg"/>
    </supportedMimeTypes>
    <supportedInputTypes>
      <input type="TEXT_ALPHANUMERIC"/>
      <input type="AUDIO"/>
    </supportedInputTypes>
    <requiresAudioLabels>false</requiresAudioLabels>
  </config>
</readingSystemAttributes> 

7.3.2 serviceAttributes

If the DAISY Online Service supports dynamic menus, the DYNAMIC_MENUS operation element must be included in the supportedOptionalOperations type in serviceAttributes. Optional functionality such as "search" and "back" support for the getQuestions operation may be specified using elements such as supportsSearch and supportsServerSideBack.

7.3.2.1 Example: serviceAttributes

<serviceAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <serviceProvider id="gy-zenith" />
  <service id="gy-zenith-libraryServiceDeluxe" />
  <supportsServerSideBack>true</supportsServerSideBack>
  <supportsSearch>true</supportsSearch>
  <supportedUplinkAudioCodecs>
    <codec>audio/mpeg</codec>
  </supportedUplinkAudioCodecs>
  <supportsAudioLabels>true</supportsAudioLabels>
  <supportedOptionalOperations>
    <operation>DYNAMIC_MENUS</operation>
    <operation>SET_BOOKMARKS</operation>
    <operation>GET_BOOKMARKS</operation>
    <operation>SERVICE_ANNOUNCEMENTS</operation>
    <operation>PDTB2_KEY_PROVISION</operation>
  </supportedOptionalOperations>
  <accessConfig>STREAM_AND_RESTRICTED_DOWNLOAD</accessConfig>
  <announcementsPullFrequency>120</announcementsPullFrequency>
  <progressStateOperationAllowed>true</progressStateOperationAllowed>
</serviceAttributes>

7.4 Example menu structure

7.4.1 Visual menu structure example

ID: Q-00 (multipleChoiceQuestion)
label: "Main menu. Please select menu option."
ID: C-01
label: "Search the library"
ID: C-02
label: "Updating the User Profile"
ID: Q-01 (multipleChoiceQuestion)
label: "Search menu."
ID: Q-02-1 (inputQuestion)
inputTypes: "TEXT_ALPHANUMERIC"
label: "Your name:"

ID: Q-02-2 (inputQuestion)
inputTypes: "TEXT_ALPHANUMERIC"
label: "Your address:"

ID: Q-02-3 (multipleChoiceQuestion)
label: "Your gender:"
  • Choice ID: C-02-3-01
    label: "Male"
  • Choice ID: C-02-3-02
    label: "Female"
ID: C-01-01
label: "This week newly coming books"
ID: C-01-02
label: "Book Search By keyword"
ID: C-01-03
label: "Voice search"
contentListRef: "weeklynew"

(end point)
ID: Q-01-02-01 (inputQuestion)
inputTypes: "TEXT_ALPHANUMERIC"
label: "Input keyword."
ID: Q-01-03-01 (inputQuestion)
inputTypes: "AUDIO"
label: "Please talk search keyword."
contentListRef: "searchresult"

(end point)
contentListRef: "voicesearch"

(end point)
label: "User Profile configured"

(end point)

7.4.2 Text menu structure example

7.4.2.1 Root menu

7.4.2.2 Root menu response C-01 leads to sub menu Q-01

7.4.2.8 Root menu response C-02 leads to sub menu with questions Q-02-1, Q-02-2 and Q-02-3

7.5 getQuestions

7.5.1 Opening a root menu

getQuestions is the operation used to implement dynamic menus functionality. The Reading System calls getQuestions with a parameter containing the userResponse. The userResponse contains the id of the menu and the response value, which is used by the Service to determine the next dynamic menu to return to the Reading System.

A Reading System will require the ability to open the root/main menu. That is, the menu that the Service makes available prior to the User making any specific selections. To achieve this, the Reading System sends the reserved id "default" as the questionId informing the Service to return the default menu. If the Service supports dynamic menus then the "default" keyword must be supported.

The service may also optionally support reserved ids "search" and "back" as indicated by serviceAttribute elements supportsSearch and supportsServerSideBack. The "search" keyword is designed to return the default search menu and "back" is designed to support a server side back (menu navigation) feature.

If the Service supports "search", the Reading System may for example allow a choice of using the "default" or "search" menu as its initial menu.

7.5.1.1 Example: getQuestions with userResponse "default"

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="default" />
  </userResponses>
</getQuestions>

7.5.1.2 Example: Response

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <multipleChoiceQuestion id="Q-00">
    <label xml:lang="en">
      <text> Main menu. Please select menu option.</text>
    </label>
    <choices>
      <choice id="C-01">
        <label xml:lang="en">
          <text>Search the library</text>
        </label>
      </choice>
      <choice id="C-02">
        <label xml:lang="en">
          <text>Update your profile</text>
        </label>
      </choice>
    </choices>
  </multipleChoiceQuestion>
</questions>

7.5.2 Selecting from multipleChoiceQuestion

When getQuestions returns a multipleChoiceQuestion, the Reading System renders the question to enable the User to make a selection. The Reading System may render the question label as text to speech (TTS) or visually using text.

For example with the question "Q-00", the Reading System will show "Main menu. Please select menu option".

The Reading System will then render each choice label providing the options from which the User chooses. In the example of question "Q-00", "Search the library" and "Update your profile " are choices on the "default" menu.

Once the User makes a selection, the Reading System then calls getQuestions with the userResponse id of the menu and selected choice. This informs the Service of the choice made and on what question it was made.

7.5.2.1 Example: getQuestions with userResponse "Q-00" and "C-01"

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="Q-00" value="C-01" />
  </userResponses>
</getQuestions>

7.5.2.2 Example: Response

By continuing this process, dynamic menus are able to represent hierarchical menu structures. In the example, the response of ID "Q-00", value "C-01" represents the option "Search menu.". The Reading System will render the label "Search menu." and will then present the associated choices to the User.

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <multipleChoiceQuestion id="Q-01">
    <label xml:lang="en">
      <text>Search menu.</text>
    </label>
    <choices>
      <choice id="C-01-01">
        <label xml:lang="en">
          <text>This week newly coming books</text>
        </label>
      </choice>
      <choice id="C-01-02">
        <label xml:lang="en">
          <text>Book Search By keyword</text>
        </label>
      </choice>
      <choice id="C-01-03">
        <label xml:lang="en">
          <text>Voice search</text>
        </label>
      </choice>
    </choices>
  </multipleChoiceQuestion>
</questions>

7.5.3 Going "back" to previous menu

Where server side back is supported, a Reading System is able to call getQuestions with the reserved id "back", which allows the User to return to the previous menu.

Support for "back" is optional and is determined by the supportsServerSideBack element in serviceAttributes. If the Service does support server side back, the Reading System has the option of rendering support for it, but this is not mandatory.

To implement the "back" option, the Service must maintain the session to enable it to keep the chain of selected menu items, i.e. executing the "back" function returns the User to the last visited menu.

7.5.3.1 Example: getQuestions with userResponse "back" at the menu position of ID "Q-01":

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="back"/>
  </userResponses>
</getQuestions>

7.5.3.2 Example: Response:

Back from ID "Q-01" returning to the previous menu, the "default" menu.

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <multipleChoiceQuestion id="Q-00">
    <label xml:lang="en">
      <text> Main menu. Please select menu option.</text>
    </label>
    <choices>
      <choice id="C-01">
        <label xml:lang="en">
          <text>Search the library</text>
        </label>
      </choice>
      <choice id="C-02">
        <label xml:lang="en">
          <text>Update your profile</text>
        </label>
      </choice>
    </choices>
  </multipleChoiceQuestion>
</questions>

7.6 Input questions

7.6.1 Input question menu

When a User selects the choice of searching for contents by keyword, an inputQuestion is returned by the Service.

An Input question supports the following three input type. "TEXT_NUMERIC", "TEXT_ALPHANUMERIC" or "AUDIO".

The input types supported by the Reading System have already been supplied to the Service as part of the readingSystemAttributes. This ensures the Service only returns input types that are supported by the Reading System.

7.6.1.1 Example: getQuestions with userResponse "Q-01" and "C-01-02"

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="Q-01" value="C-01-02" />
  </userResponses>
</getQuestions>

7.6.1.2 Example: Response

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <inputQuestion id="Q-01-02-01">
    <inputTypes>
      <input type="TEXT_ALPHANUMERIC" />
    </inputTypes>
    <label xml:lang="en">
      <text>Input keyword.</text>
    </label>
  </inputQuestion>
</questions>

7.6.2 User interface of input

When an inputQuestion is received from the Service, the Reading System renders the question's label - in this case, for inputQuestion "Q-01-02-01", "Input keyword". The Reading System will then provide a user interface to capture User input based on the supplied input type.

For example a Reading System may render a spin control for capturing numeric data ("TEXT_NUMERIC") or may simply render a standard text control as it would for text input ("TEXT_ALPHANUMERIC"). For an "AUDIO" input type, a Reading System would use a microphone and recording key.

Once the input has been captured by the Reading System, it calls getQuestions with the data captured to return it to the Service.

7.6.2.1 Example: getQuestions with userResponse "Q-01-02-01" and " three little pigs":

The Following example shows "three little pigs" as a book search query.

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="Q-01-02-01" value="three little pigs" />
  </userResponses>
</getQuestions>

7.6.2.2 Example: Response

The getQuestions response will then contain a reference to a content list containing the search results.

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <contentListRef>L200</contentListRef>
</questions>

7.6.3 Combination of questions

To support an advanced search, it is possible to combine two or more questions in the search query stage.

As the result of the initial inputQuestion, the Service may return another inputQuestion. For example, as the result of the inputQuestion for author name, another question for issued date can be asked. When using this technique, it is possible to narrow down the search results by chaining together many questions.

Dynamic menus support another way to combine questions. The questions type supports the ability to supply many multipleChoiceQuestion and/or inputQuestion in a single userResponse.

The following example of "Updating the User Profile" shows how several questions may be combined into a single getQuestions call.

7.6.3.1 Example: getQuestions with userResponse "C-02" at "Q-00":

This example shows the userResponse for question Q-00, with selection C-02 "Updating the User Profile".

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="Q-00" value="C-02" />
  </userResponses>
</getQuestions>

7.6.3.2 Example: contentList

This example shows a sample questions element containing two inputQuestions and one multipleChoiceQuestion.

label: "Input your new user profile."
inputQuestion: "Your name:"
inputQuestion: "Your address:"
multipleChoiceQuestion: "Your gender:" Male / Female

The questions element may optionally have a label. This example shows "Input your new user profile".

When two or more inputQuestions, or multipleQuestions exist, each inputQuestion has a label to explain what the inputQuestion is.

The label associated with the parent questions element may be used to explain the purpose of the set of questions.

Note that a default value may be provided by the Service for an inputQuestion using the attribute defaultValue. For example, if the question was being used to edit their address, then the existing address could be passed as the defaultValue and would be rendered to the User for them to edit or leave unchanged.

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <label xml:lang="en">
    <text>Input your new user profile.</text>
  </label>
  <inputQuestion id="Q-02-1">
    <inputTypes>
      <input type="TEXT_ALPHANUMERIC" />
    </inputTypes>
    <label xml:lang="en">
      <text>Your name:</text>
    </label>
  </inputQuestion>
  <inputQuestion id="Q-02-2">
    <inputTypes>
      <input type="TEXT_ALPHANUMERIC" />
    </inputTypes>
    <label xml:lang="en">
      <text>Your address:</text>
    </label>
  </inputQuestion>
  <multipleChoiceQuestion id="Q-02-3">
    <label xml:lang="en">
      <text>Your gender:</text>
    </label>
    <choices>
      <choice id="C-02-3-01">
        <label xml:lang="en">
          <text>Male</text>
        </label>
      </choice>
      <choice id="C-02-3-02">
        <label xml:lang="en">
          <text>Female</text>
        </label>
      </choice>
    </choices>
  </multipleChoiceQuestion>
</questions>

7.6.3.3 Example: getQuestions for a set of questions:

The following example shows a response to the set of questions containing a label end point.

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="Q-02-1" value="Margaret Asterales" />
    <userResponse questionID="Q-02-2"
                  value="Grubenstrasse 12, 8045 Zurich, Switzerland" />
    <userResponse questionID="Q-02-3" value="C-02-3-02" />
  </userResponses>
</getQuestions>

7.6.4 Label as an end point of a dynamic menu

Dynamic menus can be terminated by using a label end point. In the example of "Updating the User Profile" a label end point is returned containing the test message "Your profile has been updated successfully".

When the menu reaches the end point, the Service returns a label to inform the Reading System of the result. For example when using a search menu, if no search results were found, the Service can return the label "No title available for this search keyword". This label is normally returned to inform the Reading System of the success or failure of an action or why a contentList was not returned.

Note that a Service could alternatively return a contentListRef pointing to an empty contentList as a contentListRef may also contain a label but this operation requires the Reading System to retrieve the contentList before it can tell it is empty.

7.6.4.1 Example: Response for question of user profile configuration menu

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <label xml:lang="en">
    <text>Your profile has been updated successfully!</text>
  </label>
</questions>

7.7 Content list

7.7.1 Content list

The result of a dynamic menu may be a list of content items which is provided using the contentListRef type which is a valid dynamic menu end point.

A contentListRef cannot contain questions as it is an end point.

A dynamic menu must end with 1 of 2 end points, being a contentListRef" or label.

A contentListRef may contain an optional label which is used to hold a description of the content list, for example "List of this weeks new books".

7.7.1.1 Example: Response against getQuestions with userResponse "Q-01" and "C-01-01"

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <label xml:lang="en">
    <text> List of this weeks new books</text>
  </label>
  <contentListRef>L100</contentListRef>
</questions>

7.7.2 Rendering a content list

A Reading System will then need to render the content list contained in the contentListRef. The Reading System calls getContentList using the contentlistRef id to obtain the content list items.

The Reading System will then render the list to the User using the label if available to describe the list returned. The User may then select an item from the list.

A Reading System may allow the User to request more details about a content list item and could then render information about this item using data made available as part of the content item's metadata.

If the content list contain a large number of items, the results may be returned in pages using the firstItem and lastItem parameters in getContentList.

7.7.2.1 Example: Content list

<contentList xmlns="http://www.daisy.org/ns/daisy-online/" id=" L100" totalItems="2">
  <label xml:lang="en">
    <text>Please select from this weeks new titles.</text>
    <audio uri="http://example.com/static/PleaseChooseFrom.mp3" size="12342"/>
  </label>
  <contentItem id="com-example-001" category="BOOK" lastModifiedDate="2015-02-25T09:20:10Z">
    <label xml:lang="en">
      <text>Fun of cooking</text>
      <audio uri="http://example.com/content/titles/FunOf_1.mp3" size="130821"/>
    </label>
    <sample id="FunOf_1-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>Fun of homemade cupcake</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Homemade cupcake reflects tradition of family. You can find family history in the way of cooking.</dc:description>
      <narrator>James Green</narrator>
      <size>8119213</size>
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
  </contentItem>
  <contentItem id="com-example-002" category="BOOK" lastModifiedDate="2015-02-26T13:20:10+06:00">
    <label xml:lang="en">
      <text>True story of three little pigs</text>
      <audio uri="http://example.com/content/titles/hp_gf.mp3" size="130821"/>
    </label>
    <sample id="hp_cos-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>True story of three little pigs</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Everyone knows about three little pigs. Yes, it is very traditional fairy tale. But, nobody know about  another true story, hidden by mysterious witch.</dc:description>
      <narrator>James Bule</narrator>
      <size>8119213</size>
      <meta name="pdtb2:specVersion" content="2005-1" />    
      <meta name="cover" content="http://example.com/image.png" />
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
  </contentItem>
</contentList>

7.7.3 Sample book

When sample content is available, the Service can supply an id of the sample contents in the content's metadata. This enables a Reading System to support a user interface to open sample content.

To access the sample, a Reading System calls getContentResources, which returns the URI to the content enabling playback to the User. (Details related to opening and playback of content are not described in this document.)

Reading Systems may optionally support terminating playback of the sample book. After termination, the Reading System may return to the content list selection.

7.7.4 Going "back" to previous question from a content list

To return to the previous question from a content list, the Reading System calls getQuestions using the reserved id "back". In the example of viewing the contentListRef "weeklynew", the call to "back" would return the User to the question "Q-01"

7.8 Add content to the bookshelf

7.8.1 Adding content

Provided that the contentItem does not have a child element multipleChoiceQuestion, the default action is always addContentToBookshelf. The Reading System may request confirmation from the User prior to adding the content to the bookshelf.

To add the content to the bookshelf, the Reading System calls addContentToBookshelf. The Reading System is able to call two or more addContentToBookshelf operations when the User has selected multiple content items.

When a book is successfully added to the bookshelf, the Reading System may choose to start playback or show the bookshelf or may return to the content list. This depends on the Reading System's design.

7.8.2 Bookshelf

After a Reading System has called addContentToBookshelf, the content will be available on the bookshelf.

To retrieve the bookshelf, the Reading System calls getContentList with the reserved id "bookshelf". The Reading System may then allow the User to select and play content from bookshelf. (Details related to listing the bookshelf are not described in this document.)

7.8.3 Playback of bookshelf content item

Instead of returning to either the bookshelf or content list, the Reading System is able to start playback of the content. A Reading System calls getContentResources to get the relevant URIs and uses them to begin playback. (Details related to listing the bookshelf are not described in this document.)

The particular Reading System behavior once the content list endpoint has been reached is dependent on the Reading System's design.

7.9 Advanced Dynamic menu

7.9.1 Support of advanced dynamic menus

Advanced dynamic menus provide support for a content item to have its own menu. This is used when the default action of addContentToBookshelf is not adequate, i.e. a Service wishes to provide multiple actions for a given content item. For example, a Service may wish to support actions such as "Loan to Internet bookshelf", "Loan by CD", or "Mark as favorites" for a given content item.

Advanced dynamic menu allows the Service to attach a multipleChoiceQuestion to a contentItem containing the required actions. Note that each content item may contain a different action list. For example, if an item cannot be loaned by CD, then the "Loan to CD" option may not be included for that content item.

To use advanced dynamic menus, a Reading System must set supportsAdvancedDynamicMenus to true. When this value is false, the Service must not add a multipleChoiceQuestion to content items.

7.9.1.1 Example: readingSystemAttributes

<readingSystemAttributes xmlns="http://www.daisy.org/ns/daisy-online/">
  <manufacturer>ACME Corporation</manufacturer>
  <model>Pro Phantom III</model>
  <serialNumber>64321</serialNumber>
  <version>1.23</version>
  <config>
    <accessConfig>STREAM_ONLY</accessConfig >
    <supportsMultipleSelections>false</supportsMultipleSelections>
    <supportsAdvancedDynamicMenus>false</supportsAdvancedDynamicMenus>
    <preferredUILanguage>en</preferredUILanguage>
    <supportedContentFormats>
      <contentFormat>ANSI/NISO Z39.86-2005</contentFormat>
      <contentFormat>Daisy 2.02</contentFormat>
    </supportedContentFormats>
    <supportedContentProtectionFormats />
    <supportedMimeTypes>
      <mimeType type="text/plain" xml:lang="en"/>
      <mimeType type="audio/mpeg"/>
    </supportedMimeTypes>
    <supportedInputTypes>
      <input type="TEXT_ALPHANUMERIC"/>
      <input type="AUDIO"/>
    </supportedInputTypes>
    <requiresAudioLabels>false</requiresAudioLabels>
  </config>
</readingSystemAttributes> 

7.9.2 Questions in the contentItem

The Following example shows three actions "Loan to Internet bookshelf", "Loan by CD", or "Mark as favorites" as available for each content item.

The multipleChoiceQuestion "L100_com-example-001" is assigned as options for the contentItem with id "com-example-001". This example shows how a Service can include the content id in the question id to ensure the Service knows which content item is being referred to once the action has been selected and returned.

7.9.2.1 Example: Content list

<contentList xmlns="http://www.daisy.org/ns/daisy-online/" id=" L100" totalItems="2">
  <label xml:lang="en">
    <text>Please select from this weeks new titles.</text>
    <audio uri="http://example.com/static/PleaseChooseFrom.mp3" size="12342"/>
  </label>
  <contentItem id="com-example-001" category="BOOK" lastModifiedDate="2015-02-25T09:20:10Z">
    <label xml:lang="en">
      <text>Fun of cooking</text>
      <audio uri="http://example.com/content/titles/FunOf_1.mp3" size="130821"/>
    </label>
    <sample id="FunOf_1-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>Fun of homemade cupcake</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Homemade cupcake reflects tradition of family. You can find family history in the way of cooking.</dc:description>
      <narrator>James Green</narrator>
      <size>8119213</size>
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
    <multipleChoiceQuestion id="L100_ com-example-001">
      <label>
        <text>What would you like to do now?</text>
      </label>
      <choices>
        <choice id="LoanByNet">
          <label>
            <text>"Loan to Internet bookshelf</text>
          </label>
        </choice>
        <choice id="LoanByCD">
          <label>
            <text>Loan by CD</text>
          </label>
        </choice>
        <choice id="Mark">
          <label>
            <text>Mark as favorites</text>
          </label>
        </choice>
      </choices>
    </multipleChoiceQuestion>
  </contentItem>
  <contentItem id="com-example-002" category="BOOK" lastModifiedDate="2015-02-26T13:20:10+06:00">
    <label xml:lang="en">
      <text>True story of three little pigs</text>
      <audio uri="http://example.com/content/titles/hp_gf.mp3" size="130821"/>
    </label>
    <sample id="hp_cos-sample"/>
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>True story of three little pigs</dc:title>
      <dc:identifier>com-example-hp_cos</dc:identifier>
      <dc:format>Daisy 2.02</dc:format>
      <dc:language>en-GB</dc:language>
      <dc:description>Everyone knows about three little pigs. Yes, it is very traditional fairy tale. But, nobody know about  another true story, hidden by mysterious witch.</dc:description>
      <narrator>James Bule</narrator>
      <size>8119213</size>
      <meta name="pdtb2:specVersion" content="2005-1" />    
      <meta name="cover" content="http://example.com/image.png" />
    </metadata>
    <accessPermission>STREAM_ONLY</accessPermission >
    <multipleChoiceQuestion id=" L100_ com-example-002">
      <label>
        <text>What would you like to do now?</text>
      </label>
      <choices>
        <choice id="LoanByNet">
          <label>
            <text>"Loan to Internet bookshelf</text>
          </label>
        </choice>
        <choice id="LoanByCD">
          <label>
            <text>Loan by CD</text>
          </label>
        </choice>
        <choice id="Mark">
          <label>
            <text>Mark as favorites</text>
          </label>
        </choice>
      </choices>
    </multipleChoiceQuestion>
  </contentItem>
</contentList>

7.9.3 Selecting from multipleChoiceQuestion of contentItem

When a multipleChoiceQuestion is provided for a contentItem, the Reading System renders this as a menu for the User to select from.

The Reading System may render the label of a question by text to speech (TTS) or by showing text in the screen. For example, in relation to the question "L100_com-example-001", the Reading System will show "What would you like to do now?" The Reading System will then render the label of each choice and allow for the User to select from these options.

In this example, the "Loan to Internet bookshelf", "Loan by CD", or "Mark as favorites" options are attached to the "Fun of cooking" contentItem. Once a choice is selected, the Reading System calls getQuestions with a userResponse containing both the menu id and selected choice.

The following example shows a sample userResponse and subsequent getQuestions response containing a label end point informing the User the title was added successfully to their bookshelf.

7.9.3.1 Example: getQuestions with userResponse "L100_com-example-001" and " LoanByNet":

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="L100_com-example-001" value="LoanByNet" />
  </userResponses>
</getQuestions>

7.9.3.2 Example: Response

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <label xml:lang="en">
    <text>The title was successfully added to your bookshelf!</text>
  </label>
</questions>

7.9.4 Actions to take as a result of an advanced dynamic menu

When getQuestion is called from a Reading System, the Service executes the corresponding actions based on the User's choice. For the Service to execute this action it will need to know both the action to perform based on the choice the User has made and the content item on which to perform the action. The Service can determine the choice from the value while the content item can be extracted from the question id.

For example, if the response contained the question id "L100_com-example-001" and the value "LoanByNet", then the choice made was "LoanByNet". The content item id is "com-example-001" which is part of the value used for the question id.

If advanced dynamic menus are not used, the Reading System can assume the action being executed is addToBookshelf. With advanced dynamic menus, the Reading System cannot make assumptions about the action selected as this is controlled by the Service, i.e. it would not make sense for a Reading System to auto start playback of a content item when using advanced dynamic menus.

The Service returns a questions type as a result of getQuestions. This means the Service can return a label or contentListRef as an end point of a dynamic menu or a further menu containing a combination of multipleChoiceQuestion or inputQuestion elements.

Since Reading Systems have no way of knowing what actions are being performed as the result of a choice, Reading Systems simply continue to render provided questions until end points are reached.

7.10 Other Examples

7.10.1 Example of supportsMultipleSelections

The allowMultipleSelections switch can be used to inform a Reading System that the Service can accept multiple selections from a given multipleChoiceQuestion but only when the Reading System has stated it can support them. The Reading System declares it can support accepting more than one selection for a multiple choice questions using the supportsMultipleSelections element in the readingSystemAttributes.

This results in a userResponse containing multiple rows, each containing the same question id yet a different choice value.

When a Reading System supports multiple selections, it must look at the allowMultipleSelections attribute on the question to determine if multiple choices are allowed by the Service for this question.

If the Reading System does not support multiple selections, the Service cannot provide menu items with the allowMultipleSelections attribute set to "true".

The following example shows multiple choice questions requesting the User to select their favorite search categories. The User is able to choose from "Comedy ", "Thriller", "Biography", "History", and/or "Fairy tale". The User can select one of the choices, or if they wish, two or more choices can be selected at once.

7.10.1.1 Example: multipleChoiceQuestion with allowMultipleSelections true

<questions xmlns="http://www.daisy.org/ns/daisy-online/">
  <multipleChoiceQuestion id="q5" allowMultipleSelections="true">
    <label xml:lang="en">
      <text>Which of the following category(s) would you like to search?</text>
    </label>
    <choices>
      <choice id="c1">
        <label xml:lang="en">
          <text>Comedy</text>
        </label>
      </choice>
      <choice id="c2">
        <label xml:lang="en">
          <text>Thriller</text>
        </label>
      </choice>
      <choice id="c3">
        <label xml:lang="en">
          <text>Biography</text>
        </label>
      </choice>
      <choice id="c4">
        <label xml:lang="en">
          <text>History</text>
        </label>
      </choice>
      <choice id="c5">
        <label xml:lang="en">
          <text>Fairy tale</text>
        </label>
      </choice>
    </choices>
  </multipleChoiceQuestion>
</questions>

7.10.1.2 Example: Choice result with "Comedy" and "Thriller", two choices selected

<getQuestions xmlns="http://www.daisy.org/ns/daisy-online/">
  <userResponses>
    <userResponse questionID="q5" value="c1" />
    <userResponse questionID="q5" value="c2" />
  </userResponses>
</getQuestions>

7.10.2 Error handling case: Reading System does not support required input type

It is possible that a Reading System does not support an input type required by the Service to perform a particular action. For example, the Service may require support for "TEXT_ALPHA_NUMERIC" input for a book search, but the Reading System does not support alphabetic input.

When this occurs, the Service can return a label to inform the User that this function is not supported on this device. As the Service knows which input types are supported by the given Reading System, it may choose simply to exclude such options that cannot be supported from the menu to simplify the User experience.

The Service could return a Fault message to the Reading System but it is often better to use a label end point. The label end point allows a reason to be returned to the Reading System and allows normal processing to continue such as processing the "back" command. For this reason it is often better to use the label end point avoiding the need to raise a Fault condition.

7.10.3 Error handling case: Fault error

The DAISY Online protocol defines Fault error cases to handle error situations. Once a Fault occurs, the Service will have difficulty tracking the current selections of dynamic menu items. It will be difficult for Reading Systems to respond to getQuestions to resume suitable dynamic menu conditions.

This results in both Service and Reading System not being able to continue dynamic menu selections once a Fault condition has occured.

The Error handing / Fault management design depends on the individual Reading System design, however it is normal behavior when a Fault occurs for a Reading System to render the error message to the User and exit from the dynamic menu.