<?php
# Sistema de reconhecimento de fala. Idioma português brasileiro.
# Mostra um menu de opções e cola o resultado no aplicativo em uso.
# Feito para linux (testado no Ubuntu 10.04). Licença: Domínio público.
# (c) 2010 Sony Fermino dos Santos - http://gigawiki.com/sony/
# Fornecido sem quaisquer garantias. Use por sua conta e risco.
# Veja instruções de uso em http://gigawiki.com/sony/reconhecimento-de-fala
#
# Parte destes comentários foi redigida verbalmente com este programa.
# tempo de espera para executar operações de foco, teclas e clipboard
$sleep = 100000; # microssegundos
# identifica essa janela
$ultima_ativa = $esta_janela = pega_janela_ativa();
# abre comunicação com o Julius
$f = popen('julius -C opcoes.jconf', 'r');
while (true) {
# aguarda a saída do julius
$linha = fread($f, 4096);
# separa as frases candidatas
preg_match_all('/sentence...(.*)/m', $linha, $matches);
$opcoes = $matches[1];
# ignora a respiração
$opcoes = array_map('trim', $opcoes);
if (in_array(utf8_encode('há um ano'), $opcoes)) {
ignora('respiração', opcoes);
continue;
}
# salva a janela ativa
$janela_ativa = pega_janela_ativa();
# loop para certificar-se de que foi escolhida a opção desejada
while (true) {
# monta um menu com as opções
$ret = menu($opcoes);
if ($ret) {
# dá opções de pontuação
$pontos = str_split('.,;:!?');
array_unshift($pontos, '');
$ucfirst = mb_strtoupper(mb_substr($ret, 0, 1, 'utf-8'), 'utf-8') .
mb_substr($ret, 1, 256, 'utf-8');
$pontuacoes = array();
foreach(array($ret, $ucfirst) as $frase)
foreach($pontos as $pt)
{
$pontuacoes[] = $frase . $pt;
}
$ret = menu($pontuacoes, 2);
# se foi cancelada, não foi escolhida a opção desejada
if (!$ret) continue;
}
break;
}
# restaura o foco
ativa($janela_ativa);
if ($ret) {
# salva o clipboard
$clip = get_clipboard();
# copia o resultado para o clipboard
set_clipboard("$ret ");
# cola
tecla("ctrl+v");
# restaura o clipboard
set_clipboard($clip);
}
}
function respira($suspiros = 1) {
global $sleep;
for($i = 0; $i < $suspiros; $i++) usleep($sleep);
}
function ativa($wid) {
global $ultima_ativa;
if ($wid != $ultima_ativa) {
shell_exec("xdotool windowactivate $wid");
$ultima_ativa = $wid;
respira();
}
}
function pega_janela_ativa() {
return shell_exec('xdotool getactivewindow');
}
function tecla($teclas) {
shell_exec("xdotool key $teclas");
respira();
}
function set_clipboard($texto) {
shell_exec("echo -n '$texto' | xsel -i -b");
respira();
}
function get_clipboard() {
return shell_exec("xsel -o -b");
}
# monta um menu com as opções (que já devem estar em utf-8)
function menu($opcoes, $etapa = 1) {
global $esta_janela;
$etapas = array(1 => 'a frase', 'a pontuação');
# monta opções de comando
$op_cmd = '';
$num_op = 0;
$tamanho = 0;
foreach($opcoes as $opcao) {
if ($opcao) {
# tira espaços repetidos
$opcao = preg_replace('/\s{2,}/', ' ', $opcao);
$op_cmd .= " '$opcao'";
$num_op++;
$tamanho += strlen($opcao);
}
}
# na escolha da frase pode haver ruídos
if ($etapa == 1) {
# se o tamanho total for pequeno, ignora.
if ($tamanho < 50) return ignora("tamanho insuficiente: $tamanho", $opcoes);
}
# trata textos
$texto = utf8_encode("Escolha " . $etapas[$etapa]);
$coluna = utf8_encode('opções');
$titulo = 'Reconhecimento de fala';
# calcula a altura
$height = $num_op * 20 + 180;
# monta comando
$comando = "zenity --list --title='$titulo' --text='$texto' --column='$coluna' --height=$height --width=500 $op_cmd";
# mostra o menu
ativa($esta_janela);
$fp = popen($comando, 'r');
respira(2 + $etapa);
# seleciona a primeira opção
tecla('Down');
# aguarda o resultado
$ret = fread($fp, 256);
fclose($fp);
# estudo para determinar tamanho mínimo a ser considerado
if (!$ret and $etapa == 1) {
echo utf8_encode("\nCancelado pelo usuário. Tamanho: $tamanho\n");
}
return trim($ret);
}
function ignora($motivo, $opcoes) {
# loga motivo
echo "\nIgnorando: " . utf8_encode($motivo . "\nOpções:\n");
foreach ($opcoes as $opcao) echo " '$opcao'\n";
return false;
}
?>