MokaByte 86 - Giugno 2004 
Televisione Digitale Interattiva
Le Xlet - II parte

di
Emanuele
Brunelli

Dopo i primi articoli introduttivi al mondo della Televisione Digitale Terrestre[1] e alle Xlet[2] vediamo di approfondire la costruzione delle applicazioni interattive nello standard MHP.
In particolare vedremo come si possono costruire interfacce grafiche e come sia possibile gestire gli eventi generati dal telecomando. Ricordiamoci che una Xlet è una particolare applicazione Java concepita per essere scaricata ed eseguita su decoder interattivi MHP(set top box).

Modello grafico

Il modello grafico definito dallo standard MHP è basato su tre differenti piani(o layers) come mostrato in Figura 1.


Figura 1
- i layer grafici dell'MHP

Partendo dal basso troviamo il Background layer che può contenere un solid color o una still image(rappresentata da un particolare frame MPEG-2, quello di tipo I), risalendo troviamo il Video layer rappresentato dal flusso A/V del canale TV o di una qualsiasi altra fonte in formato MPEG-2.
Al livello più alto troviamo il Graphics layer che può contenere la grafica creata nella Xlet, che a sua volta può essere strutturata su n-livelli sovrapposti.
Questo modello grafico è supportato da diversi package messi a disposizione dallo standard; uno dei fondamentali è Havi 1.1[6].
In tale package il container di più alto livello in una Xlet è rappresentato dalla classe org.havi.ui.HScene, che concettualmente è equivalente a java.awt.Window o java.awt.Frame ma con caratteristiche specifiche per i decoder digitali. La classe factory che ci permette di richiedere l'unica istanza della HScene è fornita dallo stesso package e si chiama org.havi.ui.HSceneFactory.
MHP supporta anche le classi AWT contenute nella versione 1.1.8 del JDK Sun ma spesso è possibile trovare un equivalente nel package Havi e che quindi dovrebbe essere preferita(es: org.havi.ui.HContainer è più specifica per MHP di java.awt.Container). Oltre ad Havi e AWT è possibile utilizzare anche un package specifico DVB[4] org.dvb.ui dove è possibile trovare classi di utilità come la DvbColor che permette di gestire anche le trasparenze tramite il parametro alpha non presente nella classe java.awt.Color.

Il font di sistema supportato in MHP è il Tiresias, che deve essere disponibile almeno nelle seguenti dimensioni:

  • 36 punti (Title)
  • 31 punti (Subtitle)
  • 26 punti (Body)
  • 24 punti (Footnote)

I decoder MHP devono gestire anche le trasparenze, almeno nei 3 livelli definiti dallo standard:

  • 0 % (opaco)
  • 100 % (completamente trasparente)
  • 30 %. di trasparenza

I formati grafici supportati sono: png, jpg, gif e mpg(I-Frame).

Vediamo un esempio di codice che recupera l'istanza di HScene e ci posiziona un HContainer e un HText.

HSceneFactory hsf = HSceneFactory.getInstance();
HScene scene = hsf.getFullScreenScene(
HScreen.getDefaultHScreen().getDefaultHGraphicsDevice());

// risoluzione a schermo pieno
scene.setSize(720,576);
scene.setLayout(null);
HContainer cont = new HContainer(50,50,650,500);
HText text = new HText(
"Casella di testo!",
160, 200, 300, 60,
new Font("Tiresias", Font.PLAIN, 26),
Color.black,
Color.white,
new HDefaultTextLayoutManager());
cont.add(text);
scene.add(cont);
scene.setVisible(true);
scene.repaint();


Gestione degli eventi del telecomando
Come mostrato in Figura 2 gli eventi associati al telecomando definiti nell'MHP sono solamente quelli numerici, le frecce di navigazione, l'OK, il tasto teletext e i 4 colorati(rosso,verde,giallo,blu).


Figura 2
- gli eventi MHP

Da notare che lo standard non definisce eventi per i tasti EXIT e BACK che sono presenti sulla quasi totalità dei decoder e che quindi generano eventi non-standard e non sempre coerenti sui vari decoder.

MHP fornisce due possibilità per la gestione degli eventi nelle Xlet:

  • il classico meccanismo java, fornito in AWT che si realizza implementando l'interfaccia java.awt.event.KeyListener negli oggetti java.awt.Component
  • le classi del package org.dvb.event.

Essendo il primo ampiamente documentato e conosciuto vediamo nel dettaglio quello specifico del DVB. Tale meccanismo è consigliabile rispetto ad AWT perché permette un uso più oculato e collaborativo nella gestione degli eventi. Infatti rispetto ad AWT dove la registrazione degli eventi è esclusiva e comprende tutti gli eventi possibili, nel modello dvb è possibile registrarsi per la notifica dei soli eventi a cui si è realmente interessati.
Le classi principali di questo package sono la EventManger e la UserEventRepository che gestiscono rispettivamente la registrazione degli eventi e il repository degli eventi a cui si è interessati.

UserEventRepository repository = new UserEventRepository("UserRepository");
repository.addAllColourKeys();

EventManager manager = EventManager.getInstance();
// this rappresenta la classe listener
manager.addUserEventListener(this, repository);

Questo approccio ha l'ulteriore vantaggio di non imporre alla Xlet di richiedere il focus tramite la HScene(come prevede il modello awt sui Component) risulta quindi essere l'unico appproccio da seguire in tutte quelle applicazioni in cui si vogliono ricevere eventi del telecomando ma non si dispone una GUI.

Nel paragrafo seguente un esempio completo che oltre a creare una GUI gestisce gli eventi relativi ai tasti colorati del telecomando.

Esempio - DVBEventsXlet.java

import java.awt.Color;
import java.awt.Font;

import javax.tv.xlet.Xlet;
import javax.tv.xlet.XletContext;
import javax.tv.xlet.XletStateChangeException;

import org.havi.ui.HContainer;
import org.havi.ui.HDefaultTextLayoutManager;
import org.havi.ui.HScene;
import org.havi.ui.HSceneFactory;
import org.havi.ui.HScreen;
import org.havi.ui.HText;
import org.havi.ui.HVisible;

import org.havi.ui.event.HRcEvent;

import org.dvb.event.UserEvent;
import org.dvb.event.UserEventListener;
import org.dvb.event.UserEventRepository;
import org.dvb.event.EventManager;


public class DVBEventsXlet implements Xlet,UserEventListener{
  private HText text;
  private HContainer cont;
  private HScene scene;
  private EventManager manager;
  private UserEventRepository repository;
  private XletContext context;
  private boolean alreadyActive = false;

  public DVBEventsXlet() {}

  public void initXlet(XletContext context) throws XletStateChangeException{
    this.context = context;
    System.out.println(this.getClass().getName()+" : Inizializzazione avvenuta!");
  }

  public void startXlet() throws XletStateChangeException{
    if (alreadyActive) {
        System.out.println(this.getClass().getName()+" : Hello Again TV World! ");
    }else {
      System.out.println(this.getClass().getName()+" : Hello TV World");
      alreadyActive = true;
      repository = new UserEventRepository("UserRepository");
      repository.addAllColourKeys();
      manager = EventManager.getInstance();
      manager.addUserEventListener(this, repository);
      HSceneFactory hsf = HSceneFactory.getInstance();
      scene = hsf.getFullScreenScene(
                  HScreen.getDefaultHScreen().getDefaultHGraphicsDevice());
      scene.setSize(720,576);
      scene.setLayout(null);
      scene.setVisible(true);
      cont = new HContainer(50,50,650,500);
      text = new HText("Nessun Tasto Premuto!", 160, 200, 300, 60,
                       new Font("Tiresias", Font.BOLD, 26), Color.black, Color.white,
                       new HDefaultTextLayoutManager());
      cont.add(text);
      scene.add(cont);
      scene.repaint();
    }
  }

  public void pauseXlet(){
    System.out.println(this.getClass().getName()+" : Xlet in pausa!");
    repository.removeAllColourKeys();
    manager.removeUserEventListener(this);
    context.notifyPaused();
  }

  public void destroyXlet(boolean unconditional) throws XletStateChangeException{
    if (unconditional) {
      repository.removeAllColourKeys();
      manager.removeUserEventListener(this);
      if(scene != null) {
        scene.setVisible(false);
        scene.removeAll();
        HSceneFactory.getInstance().dispose(scene);
        scene = null;
      }
      context.notifyDestroyed();
      System.out.println(this.getClass().getName()+" : la Xlet e' stata terminata!");
    }else {
      System.out.println(this.getClass().getName() +" : Richiesta di destroy
                                                     rifiutata!");
      throw new XletStateChangeException("no thanks!");
    }
  }

  public void userEventReceived(UserEvent event) {
    System.out.println ("userEventReceived " + event.getCode());
    switch (event.getCode()){
      case HRcEvent.VK_COLORED_KEY_0:
        text.setForeground(Color.red);
        text.setTextContent("Hai premuto rosso",HVisible.NORMAL_STATE);
        scene.repaint();
        break;
      case HRcEvent.VK_COLORED_KEY_1:
        text.setForeground(Color.GREEN);
        text.setTextContent("Hai premuto verde",HVisible.NORMAL_STATE);
        scene.repaint();
        break;
      case HRcEvent.VK_COLORED_KEY_2:
        text.setForeground(Color.YELLOW);
        text.setTextContent("Hai premuto giallo",HVisible.NORMAL_STATE);
        scene.repaint();
      break;
      case HRcEvent.VK_COLORED_KEY_3:
        text.setForeground(Color.BLUE);
        text.setTextContent("Hai premuto blu",HVisible.NORMAL_STATE);
        scene.repaint();
        break;
    }
  }
}

 

Conclusioni
Tramite i package analizzati adesso siamo in grado di creare Xlet standard MHP e costruire interfacce grafiche avanzate che possono essere controllate tramite telecomando.
Gli esempi di codice proposti come tutte le vostre future Xlet possono essere eseguite su un ottimo software open source, XletView[5], che vi permette di emulare su PC alcune funzionalità dei decoder MHP.

 

Bibliografia
[1] E. Brunelli - "Televisione Digitale Interattiva: Lo standard MHP", Mokabyte, aprile 2004, http://www.mokabyte.it/2004/04/jtdi-1.htm
[2] E. Brunelli - "Televisione Digitale Interattiva: le Xlet parte I", Mokabyte, maggio 2004, http://www.mokabyte.it/2004/05/jtdi-2.htm
[3] Multimedia Home Platform - www.mhp.org
[4] Digital Video Broadcasting - www.dvb.org
[5] XletView - http://sourceforge.net/projects/xletview/
[6] HAVI - http://www.havi.org/
[7] Java TV - http://java.sun.com/products/javatv/

Emanuele Brunelli è laureato in Scienze dell'Informazione all'Università di Bologna. Da circa 2 anni si occupa della progettazione e dello sviluppo di applicazioni Java per la Televisione Digitale Terrestre. Le sue conoscenze comprendono Analisi e Design con UML oltre che progettazione e sviluppo in ambiente Java.


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it