Development Guide

To Bookmark this document, click

BOOK MARK 35

Creating a Video Application

Published 2014-04-09 | Playing Video Tutorial. (Compatible with SDK 2.5,3.5,4.5,5.0,5.1 and 2011,2012,2013,2014 models)

This tutorial demonstrates the use of the video features of the Samsung Apps service. These are needed to create various kinds of applications, like video catch-up services and User Created Content (UCC) services. The video features are introduced by developing a sample application featuring video playback.

The tutorial application reads title, description, and URL information for each video clip from an RSS feed on a server, and then allows the user to play, stop, and pause the video, and skip forward and backward through it. The application positions the video playback in a window surrounded by graphics, and switches to a full-screen video display. It also provides volume control functions.

To use the HAS (HTTP Adaptive Streaming) features of the Samsung Applications service, see Tutorial: Creating a Video Application With HAS (HTTP Adaptive Streaming). With HAS, users can enjoy seamless video streaming service over IP networks with best possible video quality.

You can also make a video application respond to an interactive remote control such as a mobile device and create a video application using Flash.

Figure. View of the video application

Development Environment

Use Samsung Smart TV SDK to create the application. You can also use the emulator provided with the SDK to debug and test the application before uploading it in your TV. Later, you can run the application on a TV; see Testing Your Application on a TV. Note that applications may perform better on the TV than on the emulator.

You can find general instructions for creating applications in Implementing Your Application Code.

Prerequisites

To create applications that run on a TV screen, you need:

  • Samsung TV connected to the Internet
  • SDK or a text editor for creating HTML, JavaScript and CSS files (using Samsung Smart TV SDK is recommended)

Source Files

Note

files needed for the sample application are here. The common modules, images, and basic preview code needed to create the application are provided.

This tutorial does not supply video files for playback for copyright reasons. At the time of writing (May 2009), it is recommended to use either MP4 or ASF (WMV) format video.

The directory structure of the application:

Directory/FileDescription
Common/APIContains the common modules provided by the Application Manager.
CSSContains the CSS files for the application.
ImagesContains the image files for the application.
JavascriptContains the JavaScript files for the application.
config.xmlContains information for executing the application.
index.htmlThe HTML file which runs in the application.

Class Description

This section lists the classes that for part of the application and describes them.

ClassDescription
MainResponsible for key handling and coordination of all the application components.
PlayerControls the audio and video playback from the content server using a Apps Framework 2.0.
ServerHandles the retrieval of RSS feed from the data server using AJAX.
DataHandles the storage of video data within the application.
DisplayResponsible for displaying the graphics and text information using dynamic HTML.

Basic Application and Data Retrieval

This tutorial task briefly describes the initial configuration of the application.

Creating the Basic Application

  1. Start the SDK.

  2. Create a new application using the following config.xml file.

    <?xml version="1.0" encoding="UTF-8"?>
    <widget>
        <previewjs>PreviewVideoTutorial</previewjs>
        <type>user</type>
        <cpname></cpname>
        <cplogo></cplogo>
        <cpauthjs></cpauthjs>
        <ThumbIcon>Images/icon/Tutorial_Video_106.png</ThumbIcon>
        <BigThumbIcon>Images/icon/Tutorial_Video_115.png</BigThumbIcon>
        <ListIcon>Images/icon/Tutorial_Video_85.png</ListIcon>
        <BigListIcon>Images/icon/Tutorial_Video_95.png</BigListIcon>
        <ver></ver>
        <mgrver></mgrver>
        <fullwidget>y</fullwidget>
        <movie>y</movie>
        <srcctl>y</srcctl>
        <ticker>n</ticker>
        <childlock>n</childlock>
        <audiomute>n</audiomute>
        <videomute>n</videomute>
        <dcont>y</dcont>
        <widgetname></widgetname>
        <description></description>
        <width>960</width>
        <height>540</height>
        <author>
            <name>Samsung Electronics Co. Ltd.</name>
            <email></email>
            <link>http://www.sec.com</link>
            <organization>Samsung Electronics Co. Ltd.</organization>
        </author>
    </widget>
    

    The following settings are used:

    <fullwidget>y</fullwidget>

    Makes the application run in full screen mode. This affects what keys are registered by default.

    <type>user</type>

    Enables the user application feature for testing on a real TV set. This tag has no effect on the emulator.

    <movie>y</movie>

    Optimises the application behaviour for movie playback.

  3. Add the index.html file with the following code.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/div/html4/strict.dtd">
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <title>Tutorial Video App</title>
            <!-- Common App API -->
            <script type="text/javascript" src="$MANAGER_WIDGET/Common/API/widget.js"></script>
            <script type="text/javascript" src="$MANAGER_WIDGET/Common/API/TVKeyValue.js"></script>
            <script type="text/javascript" language="javascript" src="$MANAGER_WIDGET/Common/af/2.0.0/loader.js"></script>
            <!-- App code -->
            <script type="text/javascript" src="Javascript/Main.js"></script>
        </head>
        <body onload="Main.onLoad();" onunload="Main.onUnload();">
        </body>
    </html>
    

    Note

    Use $MANAGER_WIDGET/Common/API/Widget.js for running the application on TV and use Common/API/Widget.js to include the common JavaScript files for running it on simulator.

  4. Add Main.js file with the following code in the Javascript folder:

    var widgetAPI = new Common.API.Widget(),
        tvKey = new Common.API.TVKeyValue(),
        Main = {};
    
    Main.onLoad = function() {
        alert("Main.onLoad()");
    }
    
    Main.onUnload = function() {
        alert("Main.onUnload()");
    }
    
  5. Start the SDK emulator. If the alert() : Main.onLoad() message is displayed in the log manager, the application is created successfully.

Retrieving Data from the Server

To retrieve data from the server,

  1. Get the RSS data from the server.

  2. Extract from the RSS data the information about the location of the video streams, and additional information about each video. A basic RSS format is used to store the data. See the example XML code given below.

    <?xml version="1.0"?>
    <rss version="2.0">
    <channel>
      <item>
        <title>First video</title>
        <link>http://videoURL1</link>
        <description> This is a video</description>
      </item>
      <item>
        <title>Second video</title>
        <link>http://videoURL2</link>
        <description>This is another video</description>
      </item>
    </channel>
    </rss>
    

    To create the XML file,

    • Set the <title> and <description> tags with information about each video.

    • Set valid paths to video content in the <link> tags. The video content can be located on an HTTP server or in a local directory on the development computer.

      HTTP server
      Use an HTTP server:
    • For running the application on TV and emulator

    • In a production application

      Example link tag: <link>http://111.222.333.444/MyVideoApp/content/video.mp4</link>

      Local directory
      Use a local directory:
    • For running the application on the emulator

    • In the application development when no web server is available

      Example link tag: <link>c:\my\path\to\video files\another_video.mp4</link>

    Note

    The <link> tag must contain an absolute path, no matter where the video files are stored. The relative paths to video content do not work because the path is interpreted by a native plugin, and not by the web browser.

  3. Add the following code to Main.onLoad.

    if (Server.init()) {
        // Start retrieving data from server
        Server.dataReceivedCallback = function() {
                alert("All data received");
        }
    
        Server.fetchVideoList(); /* Request video information from server */
        widgetAPI.sendReadyEvent();
    } else {
        alert("Failed to initialise");
    }
    
  4. Add Server.js in the JavaScript folder with the following code:

    var Server = {
        /* Callback function to be set by client */
        dataReceivedCallback : null,
        XHRObj : null,
        url : "XML/videoList.xml"
    
    };
    
    Server.init = function() {
        var success = true;
        if (this.XHRObj) {
            this.XHRObj.destroy();
            // Saves memory
            this.XHRObj = null;
        }
        return success;
    }
    
    Server.fetchVideoList = function() {
        if (this.XHRObj == null) {
            this.XHRObj = new XMLHttpRequest();
        }
    
        if (this.XHRObj) {
            this.XHRObj.onreadystatechange = function() {
                if (Server.XHRObj.readyState == 4) {
                    Server.createVideoList();
                }
            }
            this.XHRObj.open("GET", this.url, true);
            this.XHRObj.send(null);
        } else {
            alert("Failed to create XHR");
        }
    }
    
    Server.createVideoList = function() {
        alert("XHR Object status===============================>" + this.XHRObj.status);
        var xmlElement = this.XHRObj.responseXML.documentElement,
            videoNames = [],
            videoURLs = [],
            videoDescriptions = [],
            index,
            items,
            titleElement,
            descriptionElement,
            linkElement;
    
        if (!xmlElement) {
            alert("Failed to get valid XML");
        } else {
            // Parse RSS
            // Get all "item" elements
            items = xmlElement.getElementsByTagName("item");
    
            for (index = 0; index < items.length; index++) {
                titleElement = items[index].getElementsByTagName("title")[0];
                descriptionElement = items[index].getElementsByTagName("description")[0];
                linkElement = items[index].getElementsByTagName("link")[0];
    
                if (titleElement && descriptionElement && linkElement) {
                    videoNames[index] = titleElement.firstChild.data;
                    videoURLs[index] = linkElement.firstChild.data;
                    videoDescriptions[index] = descriptionElement.firstChild.data;
                }
            }
            Data.setVideoNames(videoNames);
            Data.setVideoURLs(videoURLs);
            Data.setVideoDescriptions(videoDescriptions);
            if (this.dataReceivedCallback) {
                this.dataReceivedCallback();
                /* Notify all data is received and stored */
            }
        }
    }
    

    The value of the url variable should be the path to the RSS XML file that was created. There are two options for the location of this file:

    • On an HTTP server This can be the same web server that is used for testing applications on TV. The Apache server installed with the SDK can be used.

      Example url: http://111.222.333.444/MyVideoApp/videoList.xml

    • In a local folder inside the application This is not as flexible as using an HTTP server. If the application is running on a TV, it needs to be synchronised each time the XML file is changed. This option can be used with the emulator, and it does not require a web server. To use this option, create a new folder alongside the other folders in the application (Images , Javascript) and name it XML. Then use a relative path for url variable.

      Example url : XML/videoList.xml

  5. Add Data.js in the JavaScript folder and add the following code.

    var Data = {
        videoNames : [],
        videoURLs : [],
        videoDescriptions : []
    
    };
    
    Data.setVideoNames = function(list) {
        this.videoNames = list;
    }
    
    Data.setVideoURLs = function(list) {
        this.videoURLs = list;
    }
    
    Data.setVideoDescriptions = function(list) {
        this.videoDescriptions = list;
    
    }
    
    Data.getVideoURL = function(index) {
    
        var url = this.videoURLs[index];
        if (url) {    // Check for undefined entry (outside of valid array)
            return url;
        } else {
            return null;
        }
    }
    
    Data.getVideoCount = function() {
        return this.videoURLs.length;
    }
    
    Data.getVideoNames = function() {
        return this.videoNames;
    }
    
    Data.getVideoDescription = function(index) {
        var description = this.videoDescriptions[index];
    
        if (description)// Check for undefined entry (outside of valid array) {
            return description;
        } else {
            return "No description";
    
        }
    }
    
  6. To include the JavaScript files in the main HTML structure, add the following code in the index.html file:

    <script type="text/javascript" src="Javascript/Server.js"></script>
    <script type="text/javascript" src="Javascript/Data.js"></script>
    

When the application is run in the emulator, the following message appears in the log manager.

alert() : All data received

The Server JavaScript object that was just created calls back to the Main JavaScript object when the XML data is loaded and parsed successfully.

The following message is displayed if there is an error in the web server configuration or the URL used for the XML file. XXX is the HTTP error code (for example, 404 means “Not found”).

alert() : XML Server Error XXX

The following message is displayed if the XML structure in the file contains errors (for example, a tag such as <link> without a closing tag </link>).

alert() : Failed to get valid XML

A message is sent to the log when data is received. Actions can be executed for this event using the data retrieved.

Video Playback

This tutorial task explains adding code to the application to play the first video in the XML list in a small window on the display.

Creating a Box for Video Playback

In this section, a box on the display for the video to be played in is created. The box consists of 4 .png graphic files, with opaque pixels in the border and transparent pixels in the centre. The transparent pixels allow the video to show through, and the opaque pixels hide the video (video is behind the web browser graphics in the TV z-order).

  1. Add the following code inside the <body> tag of index.html.

    <!-- Layout begins -->
    
    <div id="main">
        <div id="logo">Video Tutorial</div>
        <div id ="rightHalf">
            <div id="videoBox_top"></div>
            <div id="videoBox_left"></div>
            <div id="videoBox_right"></div>
            <div id="videoBox_bottom"></div>
        </div>
    </div>
    
  2. Add Main.css file to the CSS folder and add the code below.

    /* Defaults */
    
    {
        padding: 0;
        margin: 0;
        border: 0;
        position: relative;
        color:#FFFFFF;
        background-color: transparent;
    }
    
    /* Layout */
    
    body {
        width: 960px;
        height: 540px;
    
    }
    
    #main {
         position: absolute;
         left: 0px;
         top: 0px;
         width: 960px;
         height: 540px;
    }
    
    #logo {
        position: absolute;
        top: 0px;
        height: 35px;
        width: 100%;
        background-image: url("../Images/BgLogo.png");
        background-repeat: repeat-x;
        font-size: 25px;
        padding-top: 3px;
        padding-left: 20px;
    }
    
    /* Right Half */
    
    #rightHalf {
        position: absolute;
        left: 420px;
        top: -5px;
        width: 540px;
        height: 540px;
    }
    
    #videoBox_top {
        position: absolute;
        left: 30px;
        top: 55px;
        width: 488px;
        height: 8px;
        background-image: url("../Images/videoBox/top.png");
    }
    
    #videoBox_left {
        position: absolute;
        left: 30px;
        top: 55px;
        width: 8px;
        height: 278px;
        background-image: url("../Images/videoBox/left.png");
    }
    
    #videoBox_right {
        position: absolute;
        left: 510px;
        top: 55px;
        width: 8px;
        height: 278px;
        background-image: url("../Images/videoBox/right.png");
    }
    
    #videoBox_bottom{
        position: absolute;
        left: 30px;
        top: 333px;
        width: 488px;
        height: 56px;
        background-image: url("../Images/videoBox/bottom.png");
    }
    

    The CSS sets the default values for the display (no margins, borders or padding to give better control over sizes); relative positioning; a colour for text; and a transparent background for the video to show through. The body size is set as full display size (960 x 540). The display is divided into sections. A <div> element called ‘main’ is set to cover the entire display. Within ‘main’, 2 <div> elements are added:

    • logo at the top Within logo, a PNG graphic file is displayed repeatedly. The graphic looks like a bar and contains the application title.
    • rightHalf at the right side Within rightHalf, the CSS creates 4 other <div> elements:
    • videoBox_top
    • videoBox_left
    • videoBox_right
    • videoBox_bottom
  3. Add a link to Main.css in the in the <head> tag of index.html file after the links to the JavaScript files.

    <!-- Style sheets -->
    
    <link rel="stylesheet" href="CSS/Main.css" type="text/css">
    
  4. Run the emulator. The ‘Video Tutorial’ title appears in the bar located at the top of the display. The box appears at the right-middle area of the display. The inside of the box shows the simulated TV picture. The box border is of solid colour, not displaying the TV picture. The video clips being played appear on the same plane as the TV picture.

Note

A more complete user interface with multiple views can be developed. For example, you can create one view for the list of videos available, and another view showing more details about the chosen video. This is done by preparing top-level <div> elements, each with their own internal layout. To switch the display, hide one and show another using Display.hide() and Display.show(). A separate JavaScript object is needed to manage each display.

Adding Basic Video Playback

This section describes adding the basic video playback functionality.

To implement the Play key to play the first video in the list,

  1. A single anchor is used for receiving the key events. Add the following code to the index.html file at the beginning of the <body> element.

    <!-- Dummy anchor as focus for key events -->
    <a href="javascript:void(0);" id="anchor" onkeydown="Main.keyDown();"></a>
    
  2. Add the following code in the Main.onLoad function to initialize a new Player module, enable key handling, and replace the current alert() call when data is loaded.

    if (Player.init() && Server.init()) {
        // Start retrieving data from server
    
        Server.dataReceivedCallback = function () {
            /* Use video information when it has arrived */
            Main.updateCurrentVideo();
        }
        Server.fetchVideoList();
        /* Request video information from server */
        // Enable key event processing
        this.enableKeys();
        widgetAPI.sendReadyEvent();
    } else {
        alert("Failed to initialise");
    }
    
  3. Add the following line to Main.onUnload().

    Player.deinit();
    
  4. Add the following functions to Main.js.

    Main.updateCurrentVideo = function () {
        Player.setVideoURL(Data.getVideoURL(0));
    }
    
    Main.enableKeys = function () {
        document.getElementById("anchor").focus();
    
    }
    
    Main.keyDown = function () {
        var keyCode = event.keyCode;
        alert("Key pressed: " + keyCode);
    
        switch(keyCode) {
            case tvKey.KEY_PLAY:
                alert("PLAY");
                Player.playVideo();
                break;
    
            default:
                alert("Unhandled key");
                break;
        }
    }
    
  5. Add the following code to Player.js.

    var Player = {
        state : -1,
        originalSource : null,
        STOPPED : 0,
        PLAYING : 1,
        PAUSED : 2,
    };
    
    Player.init = function () {
        var success = true;
        alert("success vale :  " + success);
        this.state = this.STOPPED;
        sf.service.VideoPlayer.init({
            onstatechange : function(state) {
                alert("Current State : " + state);
            },
            onend : function() {
                alert("Video ended.");
            },
            onerror : function(error) {
                alert("Error : " + error);
            }
            });
        this.setWindow();
        alert("success vale :  " + success);
        return success;
    }
    
    Player.deinit = function () {
        
    }
    
    Player.setWindow = function () {
        sf.service.VideoPlayer.setPosition({
            left : 458,
            top : 58,
            width : 472,
            height : 320
        });
    }
    
    Player.setFullscreen = function () {
        sf.service.VideoPlayer.setPosition({
            left : 0,
            top : 0,
            width : 960,
            height : 540
        });
        // sf.service.VideoPlayer.setFullScreen(true);
    }
    
    Player.setVideoURL = function (url) {
        this.url = url;
        alert("URL = " + this.url);
    }
    
    Player.playVideo = function () {
        if (this.url == null) {
            alert("No videos to play");
    
        } else {
            this.state = this.PLAYING;
            this.setWindow();
    
            sf.service.VideoPlayer.play({
                url : this.url,
                title : 'title'
                });
            alert("Playing...");
        }
    
    }
    
    
  6. Add the following script link to index.html .

    <script type="text/javascript" src="Javascript/Player.js"></script>
    
  7. Run the application in the emulator or on a real TV. The first video link from your XML file is played. If there is no playback, check the log manager to make sure the correct URL has been retrieved from the XML file on the server.

Video Control and Feedback

This tutorial task adds controls and displays to the video playback application. The task consists of the following parts:

Adding Video Controls

This section describes adding controls for the video playback using the remote control keys for Pause, Fast Forward, and Rewind.

  1. Add the following code in the keyDown() function of Main.js.

    Main.keyDown = function() {
        var keyCode = event.keyCode;
        alert("Key pressed: " + keyCode);
    
        switch(keyCode) {
            case tvKey.KEY_PLAY:
                alert("PLAY");
                this.handlePlayKey();
                break;
    
            case tvKey.KEY_STOP:
                alert("STOP");
                Player.stopVideo();
                break;
    
            case tvKey.KEY_PAUSE:
                alert("PAUSE");
                this.handlePauseKey();
                break;
    
            case tvKey.KEY_FF:
                alert("FF");
                break;
    
            case tvKey.KEY_RW:
                alert("RW");
                break;
            default:
                alert("Unhandled key");
                break;
        }
    }
    
  2. Add the following functions to Main.js.

    Main.handlePlayKey = function() {
    
        switch ( Player.getState() ) {
    
            case Player.STOPPED:
                Player.playVideo();
                break;
    
            case Player.PAUSED:
                Player.resumeVideo();
                break;
    
            default:
                alert("Ignoring play key, not in correct state");
                break;
        }
    }
    
    Main.handlePauseKey = function() {
        switch ( Player.getState() ) {
            case Player.PLAYING:
                Player.pauseVideo();
                break;
    
            case Player.PAUSED:
                Player.resumeVideo();
                break;
    
            default:
                alert("Ignoring pause key, not in correct state");
                break;
        }
    }
    

    Note

    The keys handled in Main.keyDown() are already registered to full-screen applications. Therefore widgetAPI.registKey() need not be called. The functions Main.handlePlayKey() and Main.handlePauseKey() have been added. Play or Pause key resumes the video playback when paused.

  3. Add the following functions to Player.js.

    Player.pauseVideo = function() {
        this.state = this.PAUSED;
        sf.service.VideoPlayer.stop();
        alert("Paused...");
    }
    
    Player.stopVideo = function() {
        if (this.state != this.STOPPED) {
            this.state = this.STOPPED;
            sf.service.VideoPlayer.stop();
            alert("Stopped");
        } else {
            alert("Ignoring stop request, not in correct state");
        }
    }
    
    Player.resumeVideo = function() {
        this.state = this.PLAYING;
        sf.service.VideoPlayer.resume();
        alert("Playing...");
    }
    
    Player.getState = function() {
        return this.state;
    }
    

The following new Player Apps Framework 2.0 API functions are used:

Pause()
Pauses the video playback. Audio stops playing and the video display shows a frozen frame.
Resume()
Resumes video playback after pausing. Audio and video begin playing again immediately.
Stop()
Stops video playback completely. Video and audio start again only if the Play() function is called specifying a URL.

The video playback can now be controlled using these keys.

Video Selection

In this tutorial task, the ability to select other videos in the list for playback is added. A list of available videos, and a description of each one will also be displayed.

The task consists of the following parts:

Playing Multiple Video Clips

In this section, key handling functionality is added for playing the next video on the list by pressing the down key on the remote control, and playing the previous video by pressing the up key on the remote control.

  1. Add the following code to the key handling switch statement of Main.keyDown().

    case tvKey.KEY_DOWN:
        alert("DOWN");
        this.selectNextVideo();
        break;
    case tvKey.KEY_UP:
        alert("UP");
        this.selectPreviousVideo();
        break;
    
  2. Add the following line to the declaration of the var Main object.

    selectedVideo: 0,
    
  3. Add the following functions to Main.js.

    Main.selectNextVideo = function() {
        Player.stopVideo();
        this.selectedVideo = (this.selectedVideo + 1) % Data.getVideoCount();
        this.updateCurrentVideo();
    }
    
    Main.selectPreviousVideo = function() {
        Player.stopVideo();
        this.selectedVideo -= 1;
        if (this.selectedVideo <0) {
            this.selectedVideo += Data.getVideoCount();
        }
        this.updateCurrentVideo();
    }
    

    The index of the selected video in the list of videos is now being tracked. The current video is stopped, and the selected video index is changed. The updateCurrentVideo() function uses this index to select a new video URL (currently it always uses the first URL). The number of videos available has to be retrieved from the Data object, for wrapping around at the ends of the list.

  4. In Main.updateCurrentVideo() function, replace the existing call to Player.setVideoURL() with the following line.

    Player.setVideoURL(Data.getVideoURL(this.selectedVideo));
    
  5. Add the following function to Data.js.

    Data.getVideoCount = function() {
        return this.videoURLs.length;
    }
    
  6. Run the application. New videos from the list can be selected by pressing the up and down keys.

Displaying the Video Title List

In this section, functionality to display a list of available titles, and highlight the currently selected one is added. The application can display a maximum of 5 titles. If there are more than 5 videos, scroll function is displayed.

  1. Add the following mark-up to the leftHalf <div> in index.html.

    <div id="videoList" class="style_videoList">
        <div id="video0"></div>
        <div id="video1"></div>
        <div id="video2"></div>
        <div id="video3"></div>
        <div id="video4"></div>
        <div id="videoCount"></div>
    </div>
    <div id="previous"></div>
    <div id="next"></div>
    
  2. Add the following code to Main.css.

    #videoList {
        position: absolute;
        left: 30px;
        top: 55px;
        width: 390px;
        height: 430px;
        background-image: url("../Images/listBox/listBox.png");
    }
    
    #video0 {
        position: absolute;
        left: 30px;
        top: 70px;
        width: 330px;
        height: 47px;
        background-repeat: no-repeat;
        padding-left: 20px;
        padding-top: 10px;
    }
    
    #video1 {
        position: absolute;
        left: 30px;
        top: 130px;
        width: 330px;
        height: 47px;
        background-repeat: no-repeat;
        padding-left: 20px;
        padding-top: 10px;
    }
    
    #video2 {
        position: absolute;
        left: 30px;
        top: 190px;
        width: 330px;
        height: 47px;
        background-repeat: no-repeat;
        padding-left: 20px;
        padding-top: 10px;
    }
    
    #video3 {
        position: absolute;
        left: 30px;
        top: 250px;
        width: 330px;
        height: 47px;
        background-repeat: no-repeat;
        padding-left: 20px;
        padding-top: 10px;
    }
    
    #video4 {
        position: absolute;
        left: 30px;
        top: 310px;
        width: 330px;
        height: 47px;
        background-repeat: no-repeat;
        padding-left: 20px;
        padding-top: 10px;
    }
    
    #videoCount {
        position: absolute;
        left: 330px;
        top: 30px;
        width: 30px;
        height: 20px;
        text-align: left;
        font-size: 12px;
    }
    
    #previous {
        position: absolute;
        left: 210px;
        top: 80px;
        width: 30px;
        height: 30px;
        background-image: url("../Images/listBox/previous.png");
        opacity: 0.2;
    }
    
    #next {
        position: absolute;
        left: 210px;
        top: 430px;
        width: 30px;
        height: 30px;
        background-image: url("../Images/listBox/next.png");
        opacity: 0.2;
    }
    

    A new area, videoList, is added to the left column of the display. There are 6 sub areas: video0, video1, video2, video3, video4, and videoCount. The previous and next areas are added for the scroll function. The video name and number are displayed in the videoList areas. The position, width and height for previous, next, videoList, and videoList ‘s sub <div> tag are specified. The background image for videoList, previous and next tag are also specified. To prevent the text from reaching up to or overlapping the selector, padding-left/top for videoList ‘s sub tags are specified.

  3. Add the following functions to Display.js.

    Display.setVideoList = function(nameList) {
        var listHTML = "",
            i=0,
            name;
    
        for (name in nameList) {
            this.videoList[i] = document.getElementById("video"+i);
            listHTML = nameList[name] ;
            widgetAPI.putInnerHTML(this.videoList[i], listHTML);
            i++;
        }
    
        this.videoList[this.FIRSTIDX].style
            .backgroundImage= "url(Images/listBox/selector.png)";
    
        if (i>5) {
            document.getElementById("next").style.opacity = '1.0';
            document.getElementById("previous").style.opacity = '1.0';
        }
        listHTML = "1 / " + i;
        widgetAPI.putInnerHTML(document.getElementById("videoCount"), listHTML);
    }
    
    Display.setVideoListPosition = function(position, move) {
        var listHTML = "",
            i = 0;
        listHTML = (position + 1) + " / " + Data.getVideoCount();
        widgetAPI.putInnerHTML(document.getElementById("videoCount"), listHTML);
        if (Data.getVideoCount() < 5) {
            for (i = 0; i < Data.getVideoCount(); i++) {
                if (i == position) {
                    this.videoList[i].style.backgroundImage= "url(Images/listBox/selector.png)";
                } else {
                    this.videoList[i].style.backgroundImage= "url(none)";
                }
            }
        } else if (
                (this.currentWindow!=this.LASTIDX && move==Main.DOWN) ||
                (this.currentWindow!=this.FIRSTIDX && move==Main.UP)
            ) {
            if (move == Main.DOWN) {
                this.currentWindow++;
            } else {
                this.currentWindow--;
            }
    
            for (var i = 0; i <= this.LASTIDX; i++) {
                if (i == this.currentWindow){
                    this.videoList[i].style.backgroundImage= "url(Images/listBox/selector.png)";
                } else {
                    this.videoList[i].style.backgroundImage= "url(none)";
                }
            }
        } else if (this.currentWindow == this.LASTIDX && move == Main.DOWN) {
            if (position == this.FIRSTIDX) {
                this.currentWindow = this.FIRSTIDX;
                for (i = 0; i <= this.LASTIDX; i++) {
                    listHTML = Data.videoNames[i] ;
                    widgetAPI.putInnerHTML(this.videoList[i], listHTML);
                    if (i == this.currentWindow) {
                        this.videoList[i].style.backgroundImage= "url(Images/listBox/selector.png)";
                    } else {
                        this.videoList[i].style.backgroundImage= "url(none)";
                    }
                }
            } else {
                for (i = 0; i <= this.LASTIDX; i++) {
                    listHTML = Data.videoNames[i + position - this.currentWindow];
                    widgetAPI.putInnerHTML(this.videoList[i], listHTML);
                }
            }
        } else if (this.currentWindow == this.FIRSTIDX && move == Main.UP) {
            if (position == Data.getVideoCount()-1) {
                this.currentWindow = this.LASTIDX;
                for (i = 0; i <= this.LASTIDX; i++) {
                    listHTML = Data.videoNames[i + position - this.currentWindow] ;
                    widgetAPI.putInnerHTML(this.videoList[i], listHTML);
                    if (i == this.currentWindow) {
                        this.videoList[i].style.backgroundImage= "url(Images/listBox/selector.png)";
                    } else {
                        this.videoList[i].style.backgroundImage= "url(none)";
                    }
                }
            } else {
                for (i = 0; i <= this.LASTIDX; i++) {
                    listHTML = Data.videoNames[i + position] ;
                    widgetAPI.putInnerHTML(this.videoList[i], listHTML);
                }
            }
        }
    }
    

    The list of video names in each video# element is displayed. When another video is selected in the list, the highlight or titles move. If the highlight is located in the top area, on pressing the up button, the highlight does not move. The titles move one area down. If the highlight is located in the bottom area, on pressing the down button, the titles move one area down without the highlight moving. The video number is displayed in the videoCount area. If the number of videos is more than 5, the opacity of the previous and the next area is set to ‘1.0’ to support the scroll function.

  4. To pass the correct information to these new functions, in the Main.onLoad() function, replace the current definition of Server.dataReceivedCallback with the following code.

    Server.dataReceivedCallback = function() {
        // Use video information when it has arrived
        Display.setVideoList(Data.getVideoNames());
        Main.updateCurrentVideo();
    }
    
  5. Add the following function to Data.js.

    Data.getVideoNames = function() {
        return this.videoNames;
    }
    
  6. Add the following code to the declaration of the var Main object.

    mute: 0,
    NMUTE: 0,
    YMUTE: 1
    
  7. In the Main.updateCurrentVideo function, add the following code.

    Display.setVideoListPosition(this.selectedVideo);
    Display.setVideoListPosition(this.selectedVideo, move);
    
  8. In the Main.keyDown function, add the following code.

    case tvKey.KEY_DOWN:
        alert("DOWN");
        this.selectNextVideo(this.DOWN);
        break;
    case tvKey.KEY_UP:
        alert("UP");
        this.selectPreviousVideo(this.UP);
        break;
    
  9. Add the following code in Main.js.

    Main.selectNextVideo = function(down) {
        Player.stopVideo();
        this.selectedVideo = (this.selectedVideo + 1) % Data.getVideoCount();
        this.updateCurrentVideo(down);
    }
    
    Main.selectPreviousVideo = function(up) {
        Player.stopVideo();
        if (--this.selectedVideo < 0) {
            this.selectedVideo += Data.getVideoCount();
        }
        this.updateCurrentVideo(up);
    }
    
  10. Run the application. A list of titles is displayed on the left side of the screen, with a highlight on the currently selected file. Pressing the up and down keys moves the highlight or the titles.

Displaying the Video Description

The RSS information retrieved from the server also contains a description for each video link. The description for the currently selected video is displayed. This is DHTML and quite similar to the previous tasks in this tutorial.

  1. Add the following mark-up to index.html, after the end of the videoBox_bottom <div>, and in the rightHalf.

    <div id="description_top"></div>
    <div id="description_bottom"></div>
    <div id="description"></div>
    
  2. Add new CSS rules for these elements.

    #description_top {
        position: absolute;
        left: 30px;
        top: 390px;
        width: 488px;
        height: 50px;
        background-image: url("../Images/descriptionBox/description_top.png");
    }
    
    #description_bottom {
        position: absolute;
        left: 30px;
        top: 440px;
        width: 488px;
        height: 50px;
        background-image: url("../Images/descriptionBox/description_bottom.png");
    }
    
    #description {
        position: absolute;
        left: 45px;
        top: 400px;
        width: 458px;
        height: 80px;
        text-align: left;
        font-size: 16px;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    

    The position, width and height for these <div> tags are specified. The background images for description_top and description_bottom, and a text attribute for description tag are also specified.

  3. Add the following function to Display.js.

    Display.status = function (status) {
        alert(status);
        widgetAPI.putInnerHTML(this.statusDiv, status);
    }
    
  4. Add the following line to Main.updateCurrentVideo().

    Display.setDescription(Data.getVideoDescription(this.selectedVideo));
    
  5. Add the following function to Data.js.

    Data.getVideoDescription = function (index) {
        var description = this.videoDescriptions[index];
        if (description) {    // Check for undefined entry (outside of valid array)
            return description;
        } else {
            return "No description";
        }
    }
    
  6. Run the application. The description of the selected video appears underneath the video window, and it changes on pressing the up or down key. You can see a list of titles on the left side of the screen, with a highlight on the one that is currently selected for playback. If you press the up or down key, you see this highlight or the titles move.

Displaying the UI Help Bar

  1. Add the following mark-up to index.html, after the end of the leftHalf <div> .

    <div id="navi">
        <div id="help_navi">
            <img src="images/navi/play.png">
            <img src="images/navi/stop.png">
            <img src="images/navi/pause.png">
            <img src="images/navi/rewind.png">
            <img src="images/navi/forward.png">
            <a class="style_navi">Video Control</a>
            <img src="images/navi/enter.png">
            <a class="style_navi">Full-screen/Window mode</a>
            <img src="images/navi/return.png">
            <a class="style_navi">Return</a>
        </div>
    </div>
    
  2. Add the following CSS rules for these elements.

    #navi {
        position: absolute;
        top: 505px;
        height: 35px;
        width: 100%;
        background-image: url("../Images/BgNavigator.png");
        background-repeat: repeat-x;
    }
    
    #help_navi {
        position: absolute;
        left: 275px;
        top: 5px;
        width: 785px;
        height: 28px;
    }
    
    .style_navi {
        bottom: 4px;
        height: 20px;
        font-size: 20px;
        padding-left: 1ex;
        margin-right: 8ex;
    }
    

    A new area navi and a sub area help_navi are added. The position, width and height for these <div> tags are specified. The background image for navi area is specified. The background repeat on is set to display it like a bar. The UI information is displayed using <img> and <a> tags.

Full-Screen Video, Screensaver, and Picture Settings

Full-Screen Video

This section describes displaying the video using the entire TV screen. This section also describes removing all graphics from the screen, resizing the video, and switching back to the original window display.

  1. Add the following functions to Display.js.

    Display.hide = function () {
        document.getElementById("main").style.display="none";
    }
    
    Display.show = function () {
        document.getElementById("main").style.display="block";
    }
    

    The common methods in DHTML for hiding and showing page elements are used. Since this is done with the top-level <div>, all graphics are hidden and shown again.

  2. Add the following function to Player.js.

    Player.setFullscreen = function () {
        sf.service.VideoPlayer.setPosition({
            left : 0,
            top : 0,
            width : 960,
            height : 540
        });
    }
    

    This function is similar to the Player.setWindow() function. The only difference is that this specifies the video to appear across the entire screen (top = 0, left = 0, width = 960, height = 540).

  3. Add the following inside the declaration of the var Main object.

    mode: 0,
    WINDOW: 0,
    FULLSCREEN: 1
    
  4. Add the following functions to Main.js.

    Main.setFullScreenMode = function () {
        if (this.mode != this.FULLSCREEN) {
            Display.hide();
            Player.setFullscreen();
            this.mode = this.FULLSCREEN;
        }
    }
    
    Main.setWindowMode = function () {
        if (this.mode != this.WINDOW) {
            Display.show();
            Player.setWindow();
            this.mode = this.WINDOW;
        }
    }
    
    Main.toggleMode = function () {
        switch (this.mode) {
            case this.WINDOW:
                this.setFullScreenMode();
                break;
            case this.FULLSCREEN:
                this.setWindowMode();
                break;
            default:
                alert("ERROR: unexpected mode in toggleMode");
                break;
        }
    }
    
  5. Add the following code to the key handling switch statement in Main.keyDown().

    case tvKey.KEY_ENTER:
    case tvKey.KEY_PANEL_ENTER:
        alert("ENTER");
        this.toggleMode();
        break;
    

    The Enter key on the remote control now toggles between full screen video mode and the original windowed mode.

  6. The display needs to be forced to window mode when the video is stopped to enable the user to select another video. This needs to happen even if video stops by itself. Add the following line inside the declaration of the var Player object.

    stopCallback: null,    // Callback function to be set by client
    
  7. Add the following code to the Player.stopVideo() function, after the call to Display.status().

    if (this.stopCallback) {
        this.stopCallback();
    }
    
  8. Add the following code to Main.onLoad() to be executed only if initialization is successful:

    Player.stopCallback = function () {
        // Return to windowed mode when video is stopped
        // (by choice or when it reaches the end)
        Main.setWindowMode();
    }
    

    Player.stopVideo() is called when the user presses the Stop button and when a video reaches the end. This makes the callback function trigger a return to windowed mode.

  9. Run the application in the emulator or on the TV. The mode can be switched to full screen and back to windowed using the Enter key. It is possible to change the volume, pause the video and skip forward and backward without leaving the full screen mode. When returning to windowed mode, the time and volume sliders are in the correct position. Although the HTML elements are hidden, they exist in the browser and their positions can be updated.

Switching the Screensaver On/Off

During video playback, the screensaver may appear. Therefore, set the screensaver off before video playback.

To set the screensaver on or off, add the following code:

  1. Add the AppsFramwork API 2.0 library to the index.html file:

    <script type='text/javascript' language='javascript' src='$MANAGER_WIDGET/Common/af/2.0.0/loader.js'></script>
    
  2. Set off the screensaver when you click on the button

    switch (keycode) {
            casetvKey.KEY_RED:
                sf.service.setScreenSaver(true);
                break;
            case tvKey.KEY_GREEN:
               sf.service.setScreenSaver(true.100);
                break;
            case tvKey.KEY_YELLOW:
               sf.service.setScreenSaver(false);
                break;
    	    ...
    

    Picture settings in video applications

    To change the picture settings in an application:

    1. Add the following code in index.html.

      <script language="javascript" type="text/javascript" src="$MANAGER_WIDGET/Common/af/2.0.0/loader.js"></script>
      
    2. Show the picture settings popup:

      sf.service.AVSetting.show(function callback(){
      //you should reset focus.
      });
      
    3. When the video playback is finished, call the callback function.

    4. hide the picture settings popup:

      sf.service.AVSetting.hide();
      
    5. Picture Setting menu can be seen on the TV display.

      Figure: Picture Setting menu

To Bookmark this document, click

BOOK MARK 35