En esta sección se verán los paradigmas de programación de NCL y LUA, cuales son sus objetivos y por qué son usados. Así mismo, se verá de forma general como programar en ambos lenguajes aplicaciones Ginga.

Para más detalles, puede ver el manual de NCL, el manual de LUA,. En esta página, también pueden verse los elementos más usados de LUA para programar en Ginga.

Paradigmas NCL y LUA

Nested Context Language - NCL

El lenguaje NCL ha sido desarrollado utilizando una estructura modular, siguiendo los principios adoptados por el W3C -(WWW) World-Wide Web Consortium. Así, los módulos para la especificación de los conectores y las plantillas,son utilizados para la creación de documentos web. Es un lenguaje declarativo que provee facilidades para especificar aspectos de interactividad, sincronismos espacial/temporal entre objetos de multimedia, adaptabilidad y soporte para múltiples dispositivos, es decir, construir aplicaciones.

La Programación Declarativa , es un paradigma de programación que está basado en el desarrollo de programas especificando o "declarando" un conjunto de condiciones, proposiciones, afirmaciones, restricciones, ecuaciones o transformaciones que describen el problema y detallan su solución. La solución es obtenida mediante mecanismos internos de control, sin especificar exactamente cómo encontrarla.

LUA

Lua se utiliza en muchas aplicaciones profesionales (por ejemplo, Photoshop Lightroom de Adobe),con énfasis en sistemas embebidos (por ejemplo, el middleware Ginga de televisión digital) y juegos (por ejemplo, World of Warcraft). Lua es actualmente el lenguaje de scripting más utilizados en juegos, tiene un sólido manual de referencia y hay destacados libros sobre el mismo. Diversas versiones de Lua han sido liberadas y utilizadas en aplicaciones reales desde su creación en 1993.

Lua es un lenguaje de programación imperativa , estructurado y bastante ligero que fue diseñado como lenguaje de script con una semántica extendible. La programación imperativa , en contraposición a la programación declarativa es un paradigma de programación que describe la programación en términos del estado del programa y sentencias que cambian dicho estado. Los programas imperativos son un conjunto de instrucciones que le indican a la computadora cómo realizar una tarea.

top

Elementos de NCL

Los elementos básicos de un archivo NCL son el <head> y el <body>.Una forma de pensar en cómo programar en NCL es respondiendo estas preguntas:


  • ¿Qué se va a mostrar?
  • ¿Dónde se va a mostrar?
  • ¿Cómo se va a mostrar?
  • ¿Cuándo se va a mostrar?
  • ¿Cómo reutilizar código?

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>(¿Dónde va?), <descriptorBase>(¿Cómo va?), <connectorBase>(¿Cuándo va?).

<regionBase> (¿Dónde 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, está 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 (notar que 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.

<descriptorBase> (¿Cómo va?)

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. Para más detalle del elemento <transitionBase>, puede ver el manual de NCL.

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

<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" />
          

Aquí se 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.

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

top

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.

<connectorBase>

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

Caso botones del control

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

Lua (Básico)

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

top

Utilizando teclas en LUA

Mediante LUA usted puede interpretar los distintos botones asociados al control remoto, como los números o las flechas del control. Para esto LUA interpreta cada botón con un string característico dentro de su modulo evt, por ejemplo el string 'CURSOR_RIGHT' representa el botón derecho del control.

¿Cómo se utiliza?

Para esto es necesario incorporar un atributo global que logre interpretar los distintos botones disponibles, para esto usted debe incorporar al código NCL el currenteKeyMaster dentro de las configuraciones de x-ginga. Esto se realiza de la siguiente forma:

        <media id="varGlobal" type="application/x-ginga-settings" descriptor="baseDesc">
          <property name="service.currentKeyMaster" value="1"/>
        </media>
        

Para que la aplicación active el uso de currentKeyMaster usted inicialmente debe habilitarlo con la tecla ENTER (el borde se pone de color verde), este también lo puede desactivar con la tecla ERASE (el borde se pone de color azul).

Con esto cada vez que usted presione una tecla, el modulo evt de GINGA asociara inmediatamente esta acción cambiando sus atributos, por esto mismo usted dentro de LUA puede identificar esto sucesos de la siguiente forma:

        if evt.class == 'key' then
          -- evt.type en este caso es es PRESS
          canvas:drawText(100,100,('TIPO DE ACCION: '..evt.type))
           -- evt.key depende del boton presionado, ej: CURSOR_RIGHT para ->
          canvas:drawText(100,140,('BOTON PRESIONADO: '..evt.key))
          canvas:flush()
        end
        
top

Paso de parámetros a diferentes medios LUA

De igual forma que NCL puede pasarle parámetros a LUA, LUA puede pasarle parámetros a NLC y con esto da la posibilidad de pasar parametros entre distintos medios LUAs.

El paso de parámetros de LUA a NCL es bastante simple, basta con utilizar el modulo evt y re-asignarle su atributo evt.value

Para utilizar este valor y incorporarlo a otro medio lua, es necesario utilizar conectores para especificar el momento en que esto se realiza. Para esto se utiliza el símbolo $get para referirse al valor recibido desde lua. Por ejemplo:

        <link xconnector="onEndAttributionSet">
          -- Cada vez que cambia el atributo
          <bind role="onEndAttribution" component="input" interface="text"/>
          -- Se setea un parametro de otro codigo ($get)
          <bind role="set" component="output1" interface="text"> 
            <bindParam name="var" value="$get"/>
          </bind>
          -- Ese parametro corresponde al atributo text contenido en input
          <bind role="get" component="input" interface="text"/>
        </link>
        
top

Uso de Módulo TCP

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
          )
          
top

Animaciones

Para incorporar animaciones a LUA no es necesario saber nada nuevo a lo aprendido hasta este punto, generalmente para poder realizar animaciones se implementan arreglos para definir las secuencia de imágenes a utilizar, finalmente mediante el uso del modulo timer de lua se logra recorrer cada cierto tiempo estas imágenes desplegándolas consecutivamente por pantalla agregando el efecto de animación.

top