Ginga y TVD
Tarea Redes de Computadores II

NCL y Lua

El siguiente es un primer acercamiento a NCL y LUA. Esta página no pretende ser un refinado material de referencia, sino que ser el punto de partida a lo que se enfrentará al aprender estos lenguajes.

En la red existe documentación muy buena sobre NCL y LUA. Para el desarrollo de la tarea se sugiere revisar ejemplos de aplicaciones, y analizar cada uno de los componentes de ellas. En el caso de NCL, al enfrentarse a una etiqueta desconocida, lo mejor es consultar el Handbook de NCL. (si la página carga muy lento, intente deteniendo la ejecución de scripts en ella). Por otro lado, la referencia de LUA junto con la descripción del módulo canvas de LUA serán muy útiles a la hora de comprender los códigos escritos en LUA.

1. NCL

Etiqueta <head>

Base <regionBase>
Base <descriptorBase>
Base <transitionBase>
Base <ruleBase>
Base <connectorBase>

Etiqueta <body>

Etiqueta <media>
Etiqueta <context> y <port>
Etiqueta <switch>
Etiqueta <link>

Documentación NCL

 

2. Lua y NCLua

Módulo Event
Módulo Canvas
Archivo tcp.lua
Manejo de strings

3. Documentación NCL y NCLua

 


1. NCL

NCL es un lenguaje descriptivo, basado en XML, que usa etiquetas del tipo <elemento>...</elemento> para definir los componentes, características y acciones de la aplicación.

Los siguientes son todas las etiquetas que pueden componer un archivo típico NCL:


Los elementos básicos de un archivo NCL son el <head> y el <body>.

EL ELEMENTO <head>

En <head> se definen las reglas, regiones, descriptores y conectores que serán utilizados en <body> para crear la aplicación. Los elementos a utilizar se agrupan en "Bases": <ruleBase>, <transtitionBase>, <regionBase>, <descriptorBase>, <connectorBase>.

<regionBase>

Es la base encargada para la especificación de regiones. Una región es la descripción de un espacio a utilizar dentro de la pantalla.. A estos se les define, al menos, una ID, y sus características espaciales: ancho, alto y distancia desde los bordes, ya sea en pixeles o porcentaje.

Ejemplo:

	<regionBase>	
		<region id="mainScreen" width="100%" height="100%" left="0" top="0" />
</regionBase>

El ejemplo anterior define una única región llamada mainScreen que ocupa el 100% de la pantalla, sin offset desde los bordes.
Además, se pueden definir también subregiones:

	<region id="rg01" width="50%" height="20%" left="0" top="0" >
		<region id="rg01a" witdh="50% height="50%" left="0" top="50%" />
		<region id="rg01b" width="50%" height="50%" left=50%" top="0" />
	</region>

Cabe descatacar que las regiones se pueden solapar unas sobre otras, sin generar errores en el script. Sin embargo, si no se define el orden no se sabe a ciencia cierta cuál se desplegará encima de otra. Así, el parámetro zIndex permite darles un orden de profundidad: un zIndex bajo indica que la región está más atrás que una con zIndex más alto:

<regionBase>
<region id="rgVideo" width="100%" height="100%" zIndex="0" />
<region id="rgQst" width="700" height="170" bottom="5" left="10" zIndex="1" />
</regionBase>

En el ejemplo anterior, la region rgQst se mostrará encima de la región rgVideo.

<descriptorBase>

Es la base que agrupa a los elementos <descriptor>, los cuales definen los valores iniciales para las propiedades de los elementos <media>. Estos valores iniciales son definidos como atributos de los elementos.

La propiedad clave a definir son las regiones. Para referirse a una región, siempre se debe hacer a través del descriptor asociado. Al menos debe tener definido una ID y la región que describe.
Ejemplo:

	<descriptorBase>	
		<descriptor id="dVideo" region="rgVideo" />
		<descriptor id="dQst" region="rgQst" transIn="tFade"/>
	</descriptorBase>

En el ejemplo, se asignó el id dVideo a la región rgVideo, y el id dQst a la región rgQst. Adicionalmente, se describe un elemento de transición de entrada a través del parámetro transIn. En la descripción de <transitionBase> se explicará el origen de la etiqueta tFade asignada.

¿Para qué sirve este descriptor? En el body del archivo NCL, se tendrá que declarar la lógica con la que los elementos <media> se despliegan y comunican entre sí. Estos elementos, tienen como condiciones iniciales para su despliege, la descripción entregada en los elementos descriptor. Así, por ejemplo un archivo multimedia de un video, podría invocar al descriptor dQst, lo que producirá que se reproduzca en la región rgQst con un efecto de entrada tFade.

<transitionBase>

Es la base encargada de la agrupación de elementos <transition>, los cuales permiten definir tipos de transiciones de entrada y salida de los elementos gráficos de la aplicación.
Como hemos visto, en el descriptor dQst hemos definido como transición de entrada a la transición tFade, la cual se especifica de la siguiente manera:

	<transitionBase>
		<transition id="tFade" type="fade" dur="0.7s" />
	</transitionBase>
Como se aprecia, tFade es una transición de tipo "fade" (puede ser también "barWipe", "irisWipe", "clockWipe" o "snakeWipe") , con una duración de 700 ms. Parámetros adicionales pueden ser consultados en el Handbook de NCL.

<ruleBase>

Es la base en donde se agrupan los elementos <rule>. Estos elementos definen reglas para usar posteriormente en los elementos <switch> y <descriptorSwitch>. Evalúan el valor de una variable de acuerdo al operador utilizado. Tienen la forma:

	<rule id="rl01" var="v" comparator="eq" value="ff44" />
que equivale a: Retornar verdadero si v="ff44".

<compositeRule> permite agrupar reglas de manera que el conjunto se evalúa como verdadero de acuerdo al operador lógico ("and" o "or"). Por ejemplo,.

	<compositeRule id="rc00" operator="and" >
		<rule id="r01" var="v" comparator="eq" value="ff44" />
		<rule id="r02" var="q" comparator="ne" value="ff44" />
	</compositeRule>	

Retornará verdadero sólo si se cumple la sentencia lógica (v=="ff44")&&(q!="ff44").

<connectorBase>

Esta base es la encargada de agrupar a los elementos connector. Los elementos <connector> son aquellos que definen la(s) causa(s) y efecto(s) en la ejecución o interacción de los elementos de media (imágenes, video, texto, etc.). Así, se definen condiciones simples o compuestas así como también acciones simples o compuestas con el fin de asignarle roles a los elementos de media que se desee estén envueltos en relaciones causa-efecto. Presionar un botón para desplegar una imagen, o esperar 10 segundos para que se detenga un video, son ejemplos de relaciones causa-efecto para elementos de media.

Los elementos de media pueden adquirir estos roles a través de la etiqueta <link>. La idea es que primero se definen todos los roles y relaciones causa-efecto, para luego asociarselas a través de <link> a cada elemento de media, en el <body> del código NCL.

En el siguiente ejemplo se muestra el uso de condiciones simples y acciones simples:

	<connectorBase>	
		<causalConnector id="cC" >
			<simpleCondition role="onBegin" />
			<simpleAction role="start" />
		</causalConnector>
	</connectorBase>

Cada vez que el elemento asociado al rol "onBegin" comience, implicará que el elemento asociado a "start" inicie como efecto. Cabe destacar que cada acción (simpleAction) debe ser correctamente asignada a un sólo elemento de media. Si se desea asignar una misma acción a más de un elemento media, se debe agregar como parámetro max="unbounded". En general, el parámetro max indica la cantidad de elementos media que pueden tener asignada una misma simpleAction.

Ahora, cuando las condiciones son complejas se puede utilizar <compoundCondition>, el cual permite múltiples <simpleCondition> como causas, de acuerdo a un operador lógico ("and" o "or"):

	<causalConnector id="cC2" >
		<compoundCondition operator="or">
			<simpleCondition role="onBegin" />
			<simpleCondition role="onBegin" />
		</compoundCondition>
		<simpleAction role="start" />
	</causalConnector>

<compoundAction> permite múltiples <simpleAction> como efecto, que se ejecutarán secuencialmente (operator="seq") o en paralelo (operator="par"):

	<causalConnector id="cC3" >		
		<simpleCondition role="onBegin" />
		<compoundAction operator="par">
			<simpleAction role="stop" max="unbounded" qualifier="par"/>
			<simpleAction role="start"/>
		</compoundAction>
	</causalConnector>

En este ejemplo, se agregan además como parámetros al rol "stop" la cantidad máxima de elementos de media que pueden tener asignado este rol (max="unbounded" implica no tener límites en la cantidad de elementos de media), y el calificador sobre el orden en el que se asignarán los roles a los eventos (qualifier="par" produce que los roles se asignen en paralelo para todos los elementos de media con este rol).

También es posible agregar parámetros a las condiciones, para así reutilizar una misma condición en diferentes elementos de media. El ejemplo más claro de este uso es la capacidad de detener un elemento de media de acuerdo al botón presionado. En vez de generar diferentes conectores causales para cada botón, es más simple dejar el botón como parámetro a definir en el momento en el que se asignen los conectores causales a determinado elemento de media:

	<causalConnector id="onKeySelecionDelayedStop">
<connectorParam name="keyCode"/>
<simpleCondition role="onSelection" key="$keyCode"/>
<simpleAction role="stop" delay="1s" />
</causalConnector>

En este ejemplo, el parámetro del keyCode es utilizado para gatillar la acción simple "stop", luego de un retardo de 1 segundo. La condición es, "si se selecciona la tecla especificada en el parámetro keyCode, el elemento de media asociado se detendrá luego de 1 segundo".


EL ELEMENTO <body>

Dentro de la etiqueta body es donde se define el contenido de la aplicación GINGA. Mientras que el header sólo se encarga de determinar el layout, las propiedades y las relaciones causa-efecto de los elementos del software, es en el body en donde éstos son invocados y especificados. Así, en body se pueden especificar contenidos de media (con <media>), otros elementos <context> anidados, elementos <switch> y relaciones <link>.

<media>

Los principales elementos body son los elementos <media>, que corresponden a aquellos que definen los componentes a exponer en la aplicación. Estos pueden ser imágenes, texto, audio, video, y en general cualquier medio soportados por el emulador o el set-top-box usado para ejecutar la aplicación GINGA. Se definen mediante un ID y deben tener, al menos, un descriptor y la ruta donde está ubicado el objeto. Por ejemplo,

	<media id="img01" descriptor="dImg01" src="media/img01.jpg" />

individualiza al archivo de medios con el id img01, le asigna la descripción con id dImg01 y tiene como fuente de origen una carpeta local en donde se guarda el archivo img01.jpg.

El siguiente ejemplo demuestra el uso de parámetros con archivos lua:

	<media id="lua" src="upvote.lua" descriptor="dLua">
<property name="voto"/>
</media>

El declarar esta propiedad permite que se pueda setear un valor en ella en el momento de vincularla con un causalConnector.

<context> y <port>

Un elemento <context> es el elemento que permite estructurar a la aplicación NCL. Puede incorporar contenidos de media, otros elementos <context> anidados, elementos <switch> y relaciones <link>. En estricto rigor, el <body> es un tipo especial de <context>, pero que representa a la aplicación completa.

El elemento <port> define, como indica su nombre, un puerto mediante el cual se puede acceder a un elemento de media, ya sea dentro del <body> como dentro de un <context>, desde el exterior. Ver más adelante el elemento "link".
Ejemplo.

	<context id="ctx01">
		<port id="p01" component="imgC" />
		<media id="imgC" descriptor="d" src="imgC.png"/>
	</context>
Para referirse a la "imgC" desde fuera del contexto, se debe decir: component="ctx01" interface="p01".
El elemento <port> en <body> señala aquellos elementos de media que se iniciarán al comenzar la aplicación.

<switch>

<switch> es un elemento encargado de realizar un cambio de componentes de media, de acuerdo a una regla asociada y ya definida en <head>.
Los media utilizados por <switch> son definidos dentro de este, por lo que para ser referidos desde fuera, se utiliza el <switchPort>.
Ejemplo:

	<switch id="sw01">
		<bindRule constituent="txt" rule="rule01"/>
		<media id="txt" src="media/text01.txt" descriptor="d01"/>
		<bindRule constituent="img" rule="rule02"/>
		<media id="img" src="media/gif01.gif" descriptor="d02"/>
	</switch>

<link>

Los elementos <link> son aquellos que permiten la interactividad y el que suceda, en general, el inicio y término de los componentes de media.
Aquí se le asigna un rol a un <media> en la relación causa-efecto definida en los conectores en <head>.
Ejemplo.

	<link xconnector="onBeginStop">
		<bind component="img02" role="onBegin" />
		<bind component="img01" role="stop" />
	</link>

Explicación: Existe un <causalConnector> llamado "onBeginStop" que definió una condición simple llamada "onBegin" y una acción simple llamada "stop". Al comenzar "img02", se detendrá "img01", es decir, dejará de ser mostrada.
Observación.
1) Para el <causalConnector> usado, todos los roles definidos deben ser usados dentro del <link>
2) En <bind> se puede utilizar el parámetro interface para referirse a un componente definido dentro de un <switch> o <context>, mediante el <switchPort> o <port>, respectivamente.

En el caso de asignar parámetros, éstos se pueden ingresar a través de un <bindParam>. En este ejemplo se asigna el valor "RED" al parámetro "keyCode", que como hemos visto anteriormente en <causalConnector> servirá para que al momento de presionar la tecla RED del control remoto se gatille el causalConnector onKeySelecionDelayedStop sobre los elementos mOpt2 y mOpt1 (al presionar la tecla RED se activa la concidión y se detiene el elemento mOpt1).

	<link xconnector="onKeySelecionDelayedStop">
<bind component="mOpt2" role="onSelection">
<bindParam name="keyCode" value="RED"/>
</bind>
<bind component="mOpt1" role="stop"/>
</link>

 


_______________________________________

DOCUMENTACIÓN DEL LENGUAJE NCL

Documentación NCL
_______________________________________



2. Lua

Lua es el lenguaje para escribir algoritmos, en caso de que se necesite realizar algún procesamiento de datos.

Se relaciona a NCL y GINGA-NCL mediante las librerías de NCLua, que entregan (hasta la fecha) herramientas para relacionarse con los eventos de causa-acción, Módulo event, y la pantalla, Módulo canvas. Un elemento LUA se define en el archivo NCL como un media más, asignándole un descriptor de región, en donde, si se desea, se puede escribir o pintar.

Módulo event

El módulo event permite la conexión del código LUA con NCL. Define la estructura utilizada para acceder a los eventos que son manejados en el código NCL (los cuales pueden ser de tipo ncl, key, tcp o user) y así rescatar por ejemplo, los valores de algun parámetro seteado en el archivo NCL. La siguiente figura muestra la relación entre un evento de tipo ncl con el archivo NCL y con el script LUA, generando un puente entre ambos para el traspaso de información de ejecución y de parámetros:




Módulo canvas

El módulo canvas permite el dibujado de componentes en pantalla, de manera similar a las descripciones realizadas a través de NCL. Así, el lenguaje LUA consta con una poderosa herramienta para generar dinámicamente contenido en pantalla.

El dibujado se realiza directamente sobre la región que fue asignada al código LUA en el archivo NCL. Algunos de los métodos disponibles son los siguientes:

	-- en lua los comentarios se inician con doble barra.

	canvas:clear() -- permite limpiar los componentes dibujados

	canvas:attrColor(r,g,b,a) -- setea el color a utilizar a continuación, en formato RGBA

	canvas:attrFont(font,size) -- setea la fuente a utilizar para el texto, junto a su tamaño.

	canvas:drawText(x,y,text) -- dibuja el texto text en la posición x,y de la región

	canvas:flush() 	
 	-- actualiza el contenido en pantalla de acuerdo a los 
	-- cambios generados en código. Siempre al modificar algo, se debe hacer flush
	-- al final.	  

La lista completa de comandos para canvas se puede revisar aquí.

Archivo tcp.lua

Este archivo es un utilitario a la hora de realizar conexiones tcp con algún servidor web. Permite la interacción del usuario, a través del código LUA, con un servidor web. Recibir información online en la aplicación interactiva, o enviar los resultados de alguna selección realizada por el usuario, son ejemplos típicos de los usos para una conexión tcp en una aplicación GINGA.

La estructura básica para uso del archivo tcp.lua es la siguiente:

	require 'tcp'
	tcp.execute(
		function()
			-- Usar funciones: connect, send, receive, disconnect
		end
	)

El uso de cada una de estas funciones se puede revisar en detalle en los ejemplos de encuentas online.

Manejo de strings

Una de las características más potentes de este lenguaje es el manejo de strings. En la documentación se podrán encontrar una gran cantidad de funciones para el manejo de strings. Algunos ejemplos son:

	-- algunas operaciones
	-- Asignaciones
	test = "hola"
	test2 = "10"
	test3 = "12"

	-- tonumber convierte el string a un valor numérico)
	suma = tonumber(test2)+tonumber(test3)
	perc = tonumber(test2)/suma*100

	-- concatenacion 
	res = "el resultado es "..perc 

	--declaracion de funciones
	function writeTitle(text)
		canvas:attrColor(255,255,255,0)
		canvas:clear()
		canvas:attrFont("vera", 24)
		canvas:drawText(40, 10, text)
		canvas:flush()
	end

	-- recuperación de variables enviadas desde NCL.
	-- en este ejemplo, la variable voto fue seteada en el causalConnector asociado
	-- al objeto media con parámetro voto (revisar <media>)
	if evt.name == 'voto' then 
if evt.value == 'opt1' then resultado = resultado+1 end end

_______________________________________

DOCUMENTACIÓN DEL LENGUAJE Lua

Documentación Lua

DOCUMENTACIÓN DE NCLUA

Documentación NCLua
_______________________________________