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.
|