Olá.
Gostaria de saber se é possível alterar, via script Lua, o atributo src de uma tag media em tempo de execução. Eis a tag de exemplo:
<media descriptor="dVideo1" src"video.wmv" type="video/mpeg" id="video1"/>
O que eu precisava é alterar a exibição do video respondendo a um evento sem com isso ter que trocar de documento NCL.
É possível?
Obrigado.
Autor: Ricardo Abdalla
1717 comentários
<bindRule constituent="video2" rule="regra2"/>
<defaultComponent component="video1"/>
<media descriptor="dVideo1" src"video1.wmv" type="video/mpeg" id="video1"/>
<media descriptor="dVideo1" src"video2.wmv" type="video/mpeg" id="video1"/>
</switch> Esse nó está dizendo o seguinte:
SE a regra "regra2" for válida, EU sou o "video2";
SENÃO eu sou o "video1". Se precisar de 5 vídeos diferentes, coloque 5 bindRule e 5 media internos. DÚVIDA: é possível mesmo tocar WMV? Achei que não! Complementando ... 2) Como crio essas regras? No cabeçalho: <head>
(...)
<ruleBase>
<rule id="regra1" var="minhaVariavel" comparator="eq" value="1"/>
<rule id="regra2" var="minhaVariavel" comparator="eq" value="2"/>
</ruleBase>
</head> Nesse caso, criei 2 regras ... a "regra1" testa se a variável de nome "minhaVariavel" é igual ("eq") a "1". A segunda testa se "minhaVariavel" é igual a "2". Poderia ter mais regras se precisasse. 3) Onde defino essa tal "minhaVariavel"? Num nó de mídia especial do tipo settings: <media id="meuNome" type="application/x-ginga-settings">
<property name="minhaVariavel" value="1"/>
</media> Um bom lugar para colocá-lo é no mesmo contexto de seu código Lua. 4) Como mudo o valor dessa variável?
Um elo faz isso. Você poderia, por exemplo, criar um elo que copia o valor que o nó Lua passa para essa variavel. 5) Sempre que eu tocar o switch ele vai reavaliar as regras? Sim, sempre que der "stop" e "start" no switch, ele vai fazer isso, o que é equivalente a trocar o src mas de um jeito mais controlado e documentado.
<question video="srcDoVideo1" question="Minha pergunta?" a="Resposta 1" b="Resposta 2" c="Resposta 3" d="Resposta 4" answer="a"/>
( ... )
</quiz> Dai gostaria de usar um código Lua para ler essa informação e transformá-la no seu programa. Por que usar uma linguagem de abstração diferente se você pode usar NCL direto? <switch id="quiz">
<bindRule rule="rQuestion1" constituent="question1"/>
<media id="question1" src="srcDoVideo1" descriptor="meuDescriptorDoVideo">
<property name="question" value="Minha pergunta?"/>
<property name="a" value="Resposta 1"/>
<property name="b" value="Resposta 2"/>
<property name="c" value="Resposta 3"/>
<property name="d" value="Resposta 4"/>
<property name="answer" value="a"/>
</media>
</switch> Quer imprimir a pergunta e as respostas na tela? Ora, faça um Lua que recebe por um elo os valores das propriedades "a", "b", "c", "d", "question" e "answer" e as usa para imprimir na tela o esperado. Sua anotação está ali do mesmo jeito. Pois bem, seu problema exige de alguma forma que use o tal XML? Ah ... então o que você precisa apenas é de uma transformação XSLT de seu XML para NCL (ou um programa que o faça). Divirta-se! Carlos
<bindRule rule="rQuestion1" constituent="question1"/>
<media id="question1" src="media/video.wmv" type="video/mpeg" descriptor="dVideo1">
<property name="question" value="Minha pergunta?"/>
<property name="a" value="Resposta 1"/>
<property name="b" value="Resposta 2"/>
<property name="c" value="Resposta 3"/>
<property name="d" value="Resposta 4"/>
<property name="answer" value="a"/>
</media>
</switch> devo definir a porta de entrada do meu documento para o switch? 2. No seu post anterior, você disse que devo definir um nó media especial para definir variaveis, como este: <media id="meuNome" type="application/x-ginga-settings">
<property name="minhaVariavel" value="1"/>
</media> Mas no exemplo da minha primeira pergunta (retirado do seu post), colocado acima, as variaveis não são do tipo x-ginga-settings, o que me confundiu. Desejo definir, além das perguntas e resposta para cada vídeo, uma variavel que indique qual é o nó de vídeo atual, visto que irei navegar entre eles. Como, afinal, devo fazer? Obrigado
se a regra "rQuestion1" for válida, então eu sou o "question1";
se a regra "rQuestion2" for válida, então eu sou o "question2";
( ... )
se a regra "rQuestionN" for válida, então eu sou o "questionN";
media "question1" (...) fim media
media "question2" (...) fim media
( ... )
media "questionN" (...) fim media
fim do switch "quiz" No contexto (o <body> por exemplo) em que está agora o quiz, posso usar as propriedades do nó interno selecionado normalmente. Então poderia ter um nó lua esperando as perguntas, opções e resposta certa para exibir: <media id="nodeLua" (...) >
<property name="question" />
<property name="a" />
<property name="b" />
<property name="c" />
<property name="d" />
<property name="answer" />
<area id="show"/>
</media> E um elo vai informar o nó lua (que é quem vai escrever por cima de seu "video.wmv" as perguntas e opções de resposta) o que deve ser exibido quando o "quiz" inicia (não sei qual seu critério para mostrar a pegunta, assumi que é o início do quiz): <link xconnector="onBeginSet">
<bind role="onBegin" component="quiz"/>
<bind role="set" component="nodeLua" interface="question" value="$getQuestion"/>
<bind role="getQuestion" component="quiz" interface="question"/>
( ... ) repita o mesmo para "a", "b", ... "answer"
</link> Pronto. Agora é criar o código Lua que exibe ( canvas:drawText ) esses valores na tela. IMPORTANTE: Ao trocar o valor da variável "minhaVariavel" para mudar a pergunta a ser feita para o usuário, você deve ter o cuidado de parar (stop) o "quiz" e iniciar (start) ele de novo para que um novo nó seja selecionado com a nova pergunta. DETALHE: Se você vai mostrar as perguntas em cima do mesmo vídeo "video.wmv", então esse vídeo não deveria estar no "quiz". É melhor que ele seja um nó de mídia externo que tem âncoras que vão disparando o quiz. Nesse caso, o conteúdo (src) dos nós internos do switch podem até ficar vazios (caso em que o nó é um temporizador). A forma que você fez se justifica se tiver um vídeo diferente para cada pergunta. 2) Você pode definir variáveis de usuário em qualquer nó com o elemento <property>. Pode também externalizar variáveis-padrão da mesma forma, como é o caso quando define um <property name="bounds"/> ou <property name="soundLevel"/> em um nó de mídia. Mas as variáveis que vai utilizar em regras, você precisa salvar em um nó settings. Explico melhor com um exemplo. O cabeçalho onde vai definir as tais regras "rQuestion1" até "rQuestionN" do exemplo acima esclarece: <rule id="rQuestion1" var="minhaVariavel" comparator="eq" value="1"/> <!-- Em português: a regra de id "rQuestion1" significa testar se a variável global "minhaVariavel" é igual ao valor "1". Ela vai ser verdadeira nesse caso ou falsa em caso contrário. --> <rule id="rQuestion2" var="minhaVariavel" comparator="eq" value="2"/>
(...)
<rule id="rQuestionN" var="minhaVariavel" comparator="eq" value="N"/> Onde N da linha de cima, obviamente é o número de sua última pergunta (digamos, 10). Note que a regra é uma informação presente no cabeçalho. Ela se baseia em variáveis globais. O lugar para você escrever variáveis globais na linguagem é um nó settings. Então, simplificadamente, você só precisa do nó settings se estiver interessado em criar uma variável que vai ser referenciada nas regras que você definir no cabeçalho. É o seu caso.
canvas:attrColor('red')
canvas:flush()
end No entanto, nada acontece. O Canvas do lua não é inicializado. O que estou fazendo de errado? 2) Como leio, em meu script lua, os valores das propertys ? Procurei algum exemplo no fórum, mas não achei. 3) O stop e o start que eu devo fazer para atualizar o nó selecionado, eu faço no lua, ou no próprio documento NCL? Desde já, obrigado! Código: <?xml version="1.0" encoding="ISO-8859-1"?>
<ncl xsi:schemaLocation="http://www.ncl.org.br/NCL3.0/EDTVProfile www.ncl.org.br/NCL3.0/profiles/NCL30EDTV.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ncl.org.br/NCL3.0/EDTVProfile" id="newDocument1">
<head>
<connectorBase>
<importBase documentURI="connectors/composerConnectorBase.conn" alias="connBase"/>
</connectorBase>
<regionBase>
<region width="1024" height="768" id="rgTV">
<region left="200" top="20" width="320" height="160" id="rgVideo1"/>
<region left="200" top="300" width="300" height="150" id="rgLua"/>
</region>
</regionBase>
<descriptorBase>
<descriptor region="rgVideo1" id="dVideo1"/>
<descriptor region="rgVideo1" id="dVideo2"/>
<descriptor region="rgLua" id="dsLua"/>
</descriptorBase>
<ruleBase>
<rule id="rQuestion1" var="codigo" comparator="eq" value="1"/>
<rule id="rQuestion2" var="codigo" comparator="eq" value="2"/>
</ruleBase>
</head>
<body> <port component="quiz" id="port_newDocument1_video1"/> <media id="globalSettings" type="application/x-ginga-settings">
<property name="codigo" value="1"/>
</media> <media id="nodeLua" src="quiz.lua" descriptor="dsLua">
<property name="codigo" />
<property name="question" />
<property name="a" />
<property name="b" />
<property name="c" />
<property name="answer" />
<area id="show"/>
</media> <switch id="quiz">
<bindRule rule="rQuestion1" constituent="video1"/>
<bindRule rule="rQuestion2" constituent="video2"/>
<media descriptor="dVideo1" src="media/video1.wmv" type="video/mpeg" id="video1">
<property name="codigo" value="1"/>
<property name="question" value="Pergunta de Teste 1?"/>
<property name="a" value="Resposta 1"/>
<property name="b" value="Resposta 2"/>
<property name="c" value="Resposta 3"/>
<property name="answer" value="a"/>
</media>
<media descriptor="dVideo2" src="media/video2.wmv" type="video/mpeg" id="video2">
<property name="codigo" value="2"/>
<property name="question" value="Pergunta de teste 2?"/>
<property name="a" value="Resposta 1"/>
<property name="b" value="Resposta 2"/>
<property name="c" value="Resposta 3"/>
<property name="answer" value="b"/>
</media>
</switch> <link id="linkSet" xconnector="connBase#onBeginSet">
<bind role="onBegin" component="quiz"/>
<bind role="onBegin" component="nodeLua" interface="show"/>
<bind role="set" component="nodeLua" interface="question" value="$getQuestion"/>
<bind role="getQuestion" component="quiz" interface="question"/>
<bind role="set" component="nodeLua" interface="codigo" value="$getCodigo"/>
<bind role="getCodigo" component="quiz" interface="codigo"/>
<bind role="set" component="nodeLua" interface="a" value="$getA"/>
<bind role="getA" component="quiz" interface="a"/>
<bind role="set" component="nodeLua" interface="b" value="$getB"/>
<bind role="getB" component="quiz" interface="b"/>
<bind role="set" component="nodeLua" interface="c" value="$getC"/>
<bind role="getC" component="quiz" interface="c"/>
<bind role="set" component="nodeLua" interface="answer" value="$getAnswer"/>
<bind role="getAnswer" component="quiz" interface="answer"/>
</link> </body>
</ncl>
minhaTabelaParaSalvar [ evt.property ] = evt.value
evt.action = 'stop'
event.post( evt ) -- estou finalizando a atribuição. Está OK?
end 3) O stop e start no quiz para mudar a pergunta exibida deve ser feita mesmo no NCL. A condição para isso pode ser, por exemplo, a escolha de uma resposta por parte do usuário.
NclLinkingConverter::createBind Warning! interfacePoint == NULL, return NULL for 'quiz' in connector 'onBeginSet'
NclLinkingConverter::createBind Warning! interfacePoint == NULL, return NULL for 'quiz' in connector 'onBeginSet'
NclLinkingConverter::createBind Warning! interfacePoint == NULL, return NULL for 'quiz' in connector 'onBeginSet'
NclLinkingConverter::createBind Warning! interfacePoint == NULL, return NULL for 'quiz' in connector 'onBeginSet'
NclLinkingConverter::createBind Warning! interfacePoint == NULL, return NULL for 'quiz' in connector 'onBeginSet' Segue em anexo as tags link do meu arquivo: <link id="linkStart" xconnector="connBase#onBeginStart">
<bind component="quiz" role="onBegin" />
<bind component="nodeLua" role="start" />
</link> <link id="linkSet" xconnector="connBase#onBeginSet">
<bind role="onBegin" component="quiz"/>
<bind role="set" component="nodeLua" interface="question" value="$getQuestion"/>
<bind role="getQuestion" component="quiz" interface="question"/>
<bind role="set" component="nodeLua" interface="codigo" value="$getCodigo"/>
<bind role="getCodigo" component="quiz" interface="codigo"/>
<bind role="set" component="nodeLua" interface="a" value="$getA"/>
<bind role="getA" component="quiz" interface="a"/>
<bind role="set" component="nodeLua" interface="b" value="$getB"/>
<bind role="getB" component="quiz" interface="b"/>
<bind role="set" component="nodeLua" interface="c" value="$getC"/>
<bind role="getC" component="quiz" interface="c"/>
<bind role="set" component="nodeLua" interface="answer" value="$getAnswer"/>
<bind role="getAnswer" component="quiz" interface="answer"/>
</link> Você sabe me dizer o que estou fazendo de errado? Desde já agradeço.