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. 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.
Para el desarrollo de la tarea se sugiere revisar los ejemplos de aplicaciones mostrados en esta pagina. Entenderlo y aplicarlos a lo que es necesario para la tarea
1. Elementos básicos de una aplicación 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.
Usted puede ver algunos ejemplos básicos de NCL aquí.
Ademas se Recomienda relizar este ejercicio
el cual usted podrá reutilizarlo posteriormente para la tarea.
Antes de ver los ejemplos es necesario entender antes la estructura básica de un código NCL, esto se describe a continuación.
1.1 Elementos de 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>(¿Donde va?), <descriptorBase>(¿Como va?), <connectorBase>(¿Cuando va?). 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:
<region id="rg01" width="50%" height="20%" left="0" top="0" /> <region id="rg02" witdh="50% height="50%" left="0" top="50%" > <region id="rg02a" width="50%" height="50%" left=50%" top="0" /> </region>
El ejemplo anterior se definen 3 regiones, entre esta la primera, llamada rg01 que ocupa el
50% de la pantalla en ancho, y el 20% de la pantalla en alto, esta además se ubica en la esquina
superior izquierda de la pantalla. La región llamada rg02a es una sub-region contenida dentro de rg02
(si se fijan la región rg02 no finaliza con /> al declararla por lo que esta base debe terminar
con un </region> y todo lo que este dentro de esto es una sub-región)
Cabe destacar 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.
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 los cuales definen si el medio se ve con transparencia, por cierto tiempo, etc.
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.
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>.
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.
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.
Aplicando lo aprendido
Con estos ejemplos básicos usted puede hacer la estructura básica para la tarea, implemente lo aprendido poder
visualizar en la aplicación GINGA los paneles solicitados en la tarea, además de un vídeo que simule el contenido
del canal.
2. Reaccionando ante eventos con NCL
En esta sección usted podrá conectar las regiones que usted definió anteriormente con eventos, como uso de teclas
del control o eventos posteriores al inicio o fin de un medio. Para esto usted debe entender el uso de los
conectores lo cuales definen la estructura de los eventos y los elementos link que definen los medios a usar en la
interactividad ante eventos.
Esta base es la encargada de agrupar a los elementos conector. 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.
<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>
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".
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>
MAS DETALLE SOBRE BASES NCL
DOCUMENTACIÓN OFICIAL DEL LENGUAJE NCL
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.
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:
![NCL-LUA](images/ginga/ncl_lua.jpg)
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í.
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.
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