Friday, February 11, 2011

How to run multiple Xlet applicaitons in one DVB service stream.

When I cleaned my backup hard driver, I found some code which makes me to recall pieces of interesting work I did in Malaysia years ago. I did iTV application consultant for a Malaysia Broadcaster, which is doing trial broadcasting of DVB HDTV at that time.

Teltext is a popular TV service in Asia, where PAL is in the dominant position. Therefore, they want to have a new version of "teltext", which is written in MHP. However, since their STB standard has not been finalized and all MHP applications are broadcasting application instead of resident application. Then, they have a problem now. How can they put two or more broadcasting application in one digital channel (service) and user can select among application only by simply clicking a button on remote control. It must be as easy as viewer clicks button to see teletext. I made a simple Xlet to help them. It might not be perfect solution. But it works. The key is that I ejected two MHP application into one service and configure one of them to be in auto start state and the other is not. I used TSBroadcaster as head end system. The headend configuration steps are too complex to be a post. But, I will put the simple version of my work here to help me to recall later.

/*
 * XletSwitcher.java
 *
 */
package blog.jia.xlet.util;

import java.util.Vector;
import java.util.Enumeration;
import javax.tv.xlet.Xlet;
import javax.tv.xlet.XletContext;

import org.dvb.application.AppAttributes;
import org.dvb.application.AppProxy;
import org.dvb.application.AppsDatabase;
import org.dvb.application.CurrentServiceFilter;
import org.dvb.application.DVBJProxy;
import org.dvb.event.EventManager;
import org.dvb.event.UserEvent;
import org.dvb.event.UserEventListener;
import org.dvb.event.UserEventRepository;
import org.havi.ui.event.HRcEvent;

/**
 *
 * @author Jia Yiyu
 */

public class XletSwitcher implements Xlet, UserEventListener {

    private  XletContext context;
    private String supertekName;
    private String appName;
    private AppProxy supertekProxy;
    private AppProxy tempProxy;
    private AppProxy activeProxy;
    private Vector appProxies;

    private AppProxy[] proxyArray;
    private boolean supertekOn;

   
    /** Creates a new instance of XletSwitcher */
    public XletSwitcher() {

    }

    /**
     * destroyXlet
     *
     * @param boolean0 boolean
     */

    public void destroyXlet(boolean boolean0) {
        //doDestroy();
    }

    /**
     * initXlet
     *
     * @param xletContext XletContext
     */

    public void initXlet(XletContext xletContext) {

        String[] args = (String[])xletContext.getXletProperty(XletContext.ARGS);

        if(args != null && args.length == 1)
            supertekName = args[0];
        else 
   supertekName = "supertek";

        appProxies = new Vector();

        //initializing key event listener.

        UserEventRepository rep = new UserEventRepository("jia");

        rep.addKey(HRcEvent.VK_TELETEXT);

        EventManager.getInstance().addUserEventListener(this, rep);

        //supertek's initalizing status is invisible.'
        supertekOn = false;

    }    

    /**
     * pauseXlet
     */
    public void pauseXlet() {
        //doPause();
    }

    /**
     * startXlet
     */
    public void startXlet() {

        // startXlet() should not block for too long, and doing UI stuff is
        // way too long.  To solve this, we start another thread to do the work
        
        //initialize the appsdatabase

        AppsDatabase appsdatabase = AppsDatabase.getAppsDatabase();

        if (appsdatabase != null) {            

            Enumeration enumeration =
                    appsdatabase.getAppAttributes(new CurrentServiceFilter());

            if (enumeration != null) {

                while (enumeration.hasMoreElements()) {

                    AppAttributes appattributes = (AppAttributes) enumeration.nextElement();                    
                    tempProxy = appsdatabase.getAppProxy(appattributes.getIdentifier());

                    if (appattributes.getName().trim().equals(supertekName)) {
                        supertekProxy = tempProxy;
                    }
                    else {
                        if(tempProxy.getState() == DVBJProxy.STARTED)
                            activeProxy = tempProxy; 
                        appProxies.add(appsdatabase.getAppProxy(appattributes.getIdentifier()));
                    }
                }
                proxyArray = (AppProxy[])appProxies.toArray();
                appProxies = null;
            }
        }
    }

    public void userEventReceived(UserEvent e) {
        if(e.getType() == HRcEvent.KEY_PRESSED) {
            if(e.getCode() == HRcEvent.VK_TELETEXT){                
                if(supertekProxy != null){
                    if(supertekOn){
                        supertekProxy.stop(true);//maybe i will use pause.
                        if(activeProxy != null) activeProxy.start();
                        supertekOn = false;
                    } else {
                        activeProxy = getActiveProxy();
                        activeProxy.stop(true);
                        supertekProxy.start();
                        supertekOn = true;
                    }
                }
            }
        }
    }


    private AppProxy getActiveProxy(){

        for (int i=0; i < proxyArray.length; i++){

            if(proxyArray[i].getState() == DVBJProxy.STARTED) return proxyArray[i];            

        }
        return null;
    }
}


No comments:

Post a Comment