quarta-feira, 21 de outubro de 2009

GNOME 3.0: GNOME-Shell e GNOME Zeitgeist

O GNOME está se aproximando da sua versão 3.0. Os carros chefes para esta nova versão são dois softwares: GNOME-Shell e GNOME Zeitgest.

Ambos alteram a forma como se interage com o desktop e com os arquivos. O GNOME-Shell substitui o gerenciador de janelas, o painel e o lançador de aplicações atuais do GNOME, criando um ambiente desktop orientado a atividades com uma interface bem diferente da atual, afinal com este software o GNOME entra finalmente para era dos desktops 3D. Com certeza esta mudança trará muito estranheza para os usuários, porém um fato que gostei bastante foi que este lançamento não "quebrou" o desktop, pelo menos não por enquanto. Algumas distribuições simplesmente param de distribuir software antigo, por exemplo, na última versão do Kubuntu é difícil instalar algumas aplicações antigas do KDE, simplesmente porque a distribuição parou de empacotar as versões mais antigas de bibliotecas. Um grande prejuízo, principalmente no caso do KDE, onde muitas aplicações ainda não foram portadas para o KDE 4.

Alguns vídeos mostrando diversas funcionalidades do GNOME-Shell pode ser encontrado na página do projeto: http://live.gnome.org/GnomeShell/Screencasts

O GNOME Zeitgeist modifica como você vê os arquivos no computador adotando uma linha cronológica, ou seja, se você quiser ver quais arquivos acessou na semana passada é possível. Este é um software que ainda não testei, mas com certeza ainda teremos a possibilidade de ver nossos arquivos em forma de árvore, se não, ficarei muito desapontado, pois não acho que poder enxergar os arquivos apenas de forma cronológica seja a melhor solução.

O Zeitgeist também indexa páginas visitadas e outras fontes de informações. A ambição do projeto é interessante, mas não sei se irá vingar. Sempre que tentei utilizar indexadores, tipo tracker ou beagle, sempre achei que eles consumiam muito processamento e memória, além disso utilizava-os muito pouco. Sendo que as funcionalidades prometidas por tais software eu conseguia obter me organizando. Espero que o Zeitgeist me faça mudar de idéia, pois nada com um software diferente para dar um novo ar a uma mesma idéia!

sexta-feira, 4 de setembro de 2009

Mate o IE6

A algum tempo diversos sites passaram a apoiar a campanha "Mate o IE6". Basta você fazer uma busca por este tema no Google e vai encontrar diversas páginas.

Bem, porque estou fazendo este post? Acabei de olhar as estatística do blog e o IE6 subiu para o segundo lugar nos browser mais usados e provavelmente muito em breve será o primeiro, sendo assim, eu peço aos visitantes que passam por aqui: considerem atualizar seus browsers!

Existem apenas vantagens em se fazer isso: browsers mais seguros, modernos e compatíveis com padrões. Este último item pode não ser muito relevante para você, mas pode ter certeza, vai melhorar cada vez mais a vida dos programadores web.

Agora me diga uma coisa, quantos serviços web você usa hoje em dia? Pode ter certeza que esse número de serviços só vai aumentar, então faça um favor para os desenvolvedores poderem concentrar-se mais nos serviços e menos nos problemas do IE6: mate-o!

quinta-feira, 16 de julho de 2009

Formatar código-fonte para postagem em blogs

No meu último post sofri para formatar o código do meu bash script. Depois de algum tempo tentando deixá-lo com uma aparência razoável pensei que deveria ter alguma coisa pronta. Depois de procurar por algum tempo, encontrei: http://formatmysourcecode.blogspot.com/

Perfeito!!!

Trabalho repetitivo? Bash neles :P

Tenho uma base de dados que contém dados de trabalhos enviados a um evento. Além disso, possuo em um diretório os trabalhos em .rtf.

O que preciso fazer? Converter cada um dos trabalhos para .pdf e inserir no cabeçalho uma imagem do evento com seu ISSN. Além disso, a partir da área, título do trabalho, palavras-chave e autores, preciso gerar uma base de dados em um formato criado por nós para fazer buscas através de javascript nos anais do evento. Para isso, fiz um script que cuida dessas duas coisas.

Como fazia tempo que não mexia com bash script, estava meio enferrujado, mas nada que uma pesquisa no Google não ajude.

Consultei os dados do banco usando SQL e exportei o resultado para um arquivo CSV delimitado por TABs.

Aproveitei a estrutura para ler arquivos apresentadas por: http://bash.cyberciti.biz/file-management/read-a-file-line-by-line/

Além disso, para padronizar o nome dos arquivos, converti todas as informações para maiúsculo, sendo que em alguns lugares precisei retirar o acento das palavras, mas mais uma vez tive uma ajudinha: http://ubuntuforums.org/showthread.php?p=6641997

Porém a conversão das letras com acento não funcionou. Poderia ter aberto o arquivo no OpenOffice e convertido, porém acreditei que existiria um jeito de fazer isso no terminal e depois de muito procurar encontrei a solução: http://wjd.nu/notes/2009. Também vou transcrevê-la para não perdé-la, pois o site não dá nenhuma link direto a ela:

2009-01-26 - unicodeencodeerror / python redirect pipe

Python has excellent Unicode support. Most of the time it just works. However, when you want to redirect non-ASCII characters to a different program through shell redirection, you will run into a UnicodeEncodeError.
See the following example:
$ locale | grep LC_CTYPE
LC_CTYPE="en_US.UTF-8"
$ python -c 'print "\u20ac 3.50"'
\u20ac 3.50
$ python -c 'print u"\u20ac 3.50"'
€ 3.50
$ python -c 'print u"\u20ac 3.50"' | cat
Traceback (most recent call last):
File "", line 1, in 
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
Python calls something like isatty(3) ("is a TTY?") on the standard out file descriptor, and when that returns 0 (false) it forces stdout to use the ascii codec. This can be quite annoying if you want to use other shell tools (awk(1), grep(1), sed(1), tr(1) etc..) to quickly search through or modify the output stream.
The solution is to replace the stdout object with one that doesn't assume that a non-terminal only likes ASCII. Add the following to your python code:
import codecs, locale, sys
sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, 'replace')
It's not real pretty, but it works :-)
$ python -c 'import codecs, locale, sys
> sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace")
> print u"\u20ac 3.50"' | cat
€ 3.50

Escrevi/copiei uma macro n{d}o OpenOffice para converter os arquivo .rtf para .pdf e adicionar o cabeçalho com as informações do evento (esta parte me tomou bastante tempo, pois apesar de existir bastante informação de como modificar o cabeçalho e como inserir uma imagem através de macros, esta parte não funcionou no OOo 3.0 disponibilizado pelo GSB para o Slackware, quer dizer, o programa travava 99,9% das vezes e até eu perceber isso, achei que estava fazendo alguma coisa errada. No OOo 2.4 também disponiblizado pelo GSB o programa trava 0.01%. Ainda vou tentar descobrir porque!): http://www.oooforum.org/forum/viewtopic.phtml?t=3772

Sub test( cArg )
Print "|"+cArg+"|"
End Sub

Sub ConvertWordToPDF( cFile )
cURL = ConvertToURL( cFile )

' Open the document.
' Just blindly assume that the document is of a type that OOo will
' correctly recognize and open -- without specifying an import filter.

oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, Array(MakePropertyValue( "Hidden", True )))

oGraph = oDoc.createInstance("com.sun.star.text.GraphicObject")
With oGraph
.GraphicURL = "file:///home/cerodrigues/kadu.jpg"
.AnchorType = com.sun.star.text.TextContentAnchorType.AS_CHARACTER
.Width = 6000
.Height = 6000
End With

oEstPagina = oDoc.StyleFamilies.getByName("PageStyles")
oPagPadrao = oEstPagina("Default")
oPagPadrao.HeaderIsOn = True
oTxtCabecalho = oPagPadrao.HeaderText
oCursorCabecalho = oTxtCabecalho.createTextCursor()
oTxtCabecalho.insertTextContent(oCursorCabecalho, oGraph, False)
'oText.insertTextContent( oCursor, oGraph, False )



cFile = Left( cFile, Len( cFile ) - 4 ) + ".pdf"
cURL = ConvertToURL( cFile )

' Save the document using a filter.
oDoc.storeToURL( cURL, Array(MakePropertyValue( "FilterName", "writer_pdf_Export" ),)

oDoc.close( True )
End Sub


Function MakePropertyValue( Optional cName As String, Optional uValue ) As com.sun.star.beans.PropertyValue
Dim oPropertyValue As New com.sun.star.beans.PropertyValue
If Not IsMissing( cName ) Then
oPropertyValue.Name = cName
EndIf
If Not IsMissing( uValue ) Then
oPropertyValue.Value = uValue
EndIf
MakePropertyValue() = oPropertyValue
End Function

Por fim, o script final ficou assim:


#!/bin/bash

# Código utilizado para consulta através do JS
# "área^diretório onde está o artigo/nome do arquivo sem extensão*título do arquivo|palavras chaves separadas por vírgula (final),$autor1@autor2@~"

rm sucesso.txt > /dev/null 2>&1
rm fracasso.txt > /dev/null 2>&1

COD_PROCESSADO=0
AREA_PROCESSADO=""
FCOUNT=0
AREA=""
NOVO="y"

FILE="./list_trabalhos_com_oral.csv"

toUpper() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").upper() )'
}

# Coloca a descrição da forma de apresentação em minúsculo, tira os acentos, remove o início do texto "Sessão de " e substitui os espaços por _ e remove qualquer caracter de controle
processFrmApr() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").lower() )' | unaccent utf-8 | sed 's,sessao de ,,' | sed 's, ,_,g' | sed 's,[[:cntrl:]],,g'
}

# Coloca a descrição da área de conhecimento em minúsculo, tira os acentos e substitui os espaços por _ e remove qualquer caracter de controle
processArCnh() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").lower() )' | unaccent utf-8 | sed 's, ,_,g' | sed 's,[[:cntrl:]],,g'
}

# Descrição dos campos em FIELDS
# FIELDS[1] = Código do Banco de Dados
# FIELDS[2] = Título do Trabalho
# FIELDS[3] = Nome do Arquivo
# FIELDS[4] = Palavras Chaves separadas por ;
# FIELDS[5] = Autor
# FIELDS[6] = Área de conhecimento
# FIELDS[7] = Tipo do Trabalho

processLine () {

  for i in `seq 1 7`;
  do
      FIELDS[$i]=$(toUpper `echo $line | awk -F'\t' '{print $'$i'}'`)
  done

  # Gera o PDF dos arquivos submetidos e o arquivo para ser utilizado na busca pelo javascript
  # Se mudou a área que está sendo processada deve-se criar o arquivo que contêm os dados da área
  echo ${FIELDS[6]}
  if [ "x${FIELDS[6]}" != "x$AREA_PROCESSADO" ]; then
      AREA_PROCESSADO=${FIELDS[6]}
      # Termina o arquivo antigo
      echo -n "~" >> $AREA.txt
      AREA=$(processArCnh ${FIELDS[6]})
      rm $AREA.txt > /dev/null 2>&1
      touch $AREA.txt
      NOVO="y"
  fi
  echo $AREA_antiga

  # Se mudar o código é um novo trabalho, então faz a conversão para PDF e insere o cabeçalho do evento
  # Se mudou o código do trabalho, finaliza esta entrada no texto utilizado pelo javascript e inicia a nova
  if [ ${FIELDS[1]} != $COD_PROCESSADO ]; then
      if [ $COD_PROCESSADO != 0 -a "x$NOVO" != "xy" ]; then
          # Termina entrada apenas se não é a primeira mudança, pois o conteúdo anterior era vazio.
          echo -n "~" >> $AREA.txt
      fi
      COD_PROCESSADO=${FIELDS[1]}
      NOVO="x"

      echo "Convertendo arquivo: "${FIELDS[3]}

      # Cria pasta de comunicação oral ou painél se não existir
      FIELDS[7]=$(processFrmApr ${FIELDS[7]})
      echo -n ${FIELDS[7]}
      if [ ! -d ${FIELDS[7]} ]; then
          mkdir ${FIELDS[7]}
      fi

      # Cria a pasta da área de conhecimento do trabalho se não existir
      FIELDS[6]=$(processArCnh ${FIELDS[6]})
      if [ ! -d ${FIELDS[7]}/${FIELDS[6]} ]; then
          mkdir ${FIELDS[7]}/${FIELDS[6]}
      fi

      # Converte o arquivo para pdf e inclui o cabeçalho do SEU
      contador=1
      FCOUNT=`expr $FCOUNT + 1`
      while [ $contador -le 5 ]; do
          if [ -f upload2009/${FIELDS[3]}.pdf ]; then
              echo "Não é necessário converter"
              echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
              cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
              break
          fi

          if [ -f upload2009/${FIELDS[3]}.rtf ]; then
              echo "Iniciando conversão"
              /usr/lib/ooo-2.4/program/soffice.bin -invisible -headless "macro:///rtf2pdf.Conversion.ConvertWordToPDF(`pwd`/upload2009/${FIELDS[3]}.rtf)"
              # Arquivo convertido com sucesso
              if [ $? == 0 ]; then
                  echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
                  cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
                  break
              fi
          else
              echo "Não é necessário converter"
              if [ -f upload2009/${FIELDS[3]}.pdf ]; then
                  echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
                  cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
                  break
              fi
          fi
          contador=`expr $contador + 1`
      done

      if [ $contador -le 5 ]; then
          echo ${FIELDS[2]} convertido com sucesso >> sucesso.txt
      else
          echo ${FIELDS[2]} não convertido >> fracasso.txt
      fi
   
      # Insere no arquivo utilizado pelo javascript os dados do trabalho
      # Insere a área, o diretório onde está o artigo, o nome do artigo sem extensão e o título do artigo
      echo -n $AREA_PROCESSADO"^"${FIELDS[7]}"/"${FIELDS[6]}"/"$FCOUNT"*"${FIELDS[2]}"|" >> $AREA.txt
   
      # Insere as palavras chaves
      for i in `seq 1 3`;
      do
          PC[$i]=$(toUpper `echo ${FIELDS[4]} | awk -F';' '{print $'$i'}'`)
          echo -n ${PC[$i]}"," >> $AREA.txt
      done
      echo -n "$" >> $AREA.txt
   
      # Insere o primeiro autor
      echo -n ${FIELDS[5]}"@" >> $AREA.txt
  # Insere os demais autores
  else
      echo -n ${FIELDS[5]}"@" >> $AREA.txt
  fi
}

BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<$FILE
while read line
do
  # use $line variable to process line in processLine() function
  processLine $line
done
exec 0<&3

# restore $IFS which was used to determine what the field separators are
IFS=$BAKIFS
exit 0


Muito legal esse monstrengo!!!

terça-feira, 30 de junho de 2009

Extrair o áudio de um vídeo no formato MP3

A linha de comando é mesmo um canivete suíço.

mencoder file.wmv -of rawaudio -oac mp3lame -ovc copy -o file.mp3


É como Master Foo disse uma vez: "There is more Unix-nature in one line of shell script than there is in ten thousands lines of C".

O google também é ótimo... achei essa linha em: http://knowledge.drun.net/viewtopic.php?id=174

domingo, 28 de junho de 2009

TORCS: O Simulador de Corrida Aberto

Estou fazendo um curso de pós-graduação na Unioeste sobre Desenvolvimento de Software e Novas Tecnologias. Até agora está um pouco chato, pois tá chovendo bastante no molhado, mas também já aprendi algumas coisas legais. Além disso, temos que desenvolver um artigo para o final do curso, sendo assim eu consegui juntar o útil com o agradável, ou seja trabalhar com desenvolvimento de jogos.

A versão final do artigo só deverá ser entregue em setembro de 2010, porém já tivemos que fazer um esboço do trabalho final. O título do trabalho que tenho até agora é: "Inteligência Artificial Aplicada a Evolução de Carros de Corrida sem Treinamento". Ainda não estou satisfeito com este título, pois acho que não sintetiza de forma clara o que quero fazer, mas como era só um esboço inicial ficou assim mesmo.

Neste projeto eu irei utilizar o jogo torcs, http://torcs.sf.net, e meu objetivo é utilizar técnicas de inteligência artificial para conseguir evolução de tempos de volta e que isto seja feito em tempo real, ou seja, durante a corrida. A idéia é fazer com que o "robô" seja sensível as mundanças da pista e tenha a sensibilidade para melhorar sua tocada, sendo assim ser capaz de chegar aos limites do carro.

O pessoal que desenvolve o torcs criou um tutorial muito legal sobre criação de "robôs": http://www.berniw.org/, através dele é possível desenvolver uma IA bastante completa, que permite um carro frear, acelerar (claro :-), passar marcha, voltar para a pista depois de uma rodada, realizar ultrapassagens e parar nos boxes.

Com todas estas características vou deixar um pouco de lado minhas brincadeiras com a CrystalSpace3D e vou me dedicar a terminar de implementar o que está descrito no tutorial, pois além de oferecer a implementação, existem muitas explicações e referências a documentações mais completas sobre os conceitos abordados. Uma ótima pedida a quem quer brincar com IA em jogos de corrida.

Com isso espero começar a contribuir também com o jogo, aproveitando o que já está implementado para oferecer um jogo completo de F1. Na verdade, não falta muito para se ter isso, o que já está implementado é bem legal para ser oferecido como um jogo, basta oferecer mais conteúdo relacionado a F1, tais como equipes e pistas. É claro que para fazer comparações com jogos comerciais ainda é necessário evoluir bastante, mas com toda a sinceridade, é o jogo de corrida mais legal que vi até agora para o mundo do software livre.

terça-feira, 9 de junho de 2009

Compilando CrystalSpace3D (CS) e Crystal Entity Layer (CEL) no Slackware 12.2

Estou brincando com a CS e a CEL por aqui. Se você pretende utilizar esta biblioteca para desenvolver jogos ou qualquer outra aplicação com recursos 3D eu diria para levar em consideração esta mensagem http://sourceforge.net/mailarchive/forum.php?thread_name=742a36470902230603y27874edaid465aec69e0f78fc%40mail.gmail.com&forum_name=crystal-main. No entanto, você é dono do seu sistema, então trabalhe com qualquer versão da biblioteca que você quiser.

Compilar tais bibliotecas é muito fácil, pois a docuemtação é simples, porém espera-se que você já tenha compilado algo, mas não deve fugir de um ./configure, make e make install e em alguns casos jam e jam install. Esta última é a ferramenta utilizada pela CS e CEL para compilar a árvore dos fontes.

A maioria das dependências utilizadas podem ser encontradas em www.slacky.eu e www.slackbuilds.org. Outra ferramenta interessante é a pkgcreate (http://www.din.uem.br/~msambinelli/download/), que facilita bastante o processo de criar pacotes a partir dos fontes.

As informações para compilar e instalar a CS está disponível em: http://www.crystalspace3d.org/docs/online/1.4/manual/Building.html#0

Algumas dependências já vêm instaladas com o Slack, são elas: zlib, libpng, libjpeg, freetype, bibliotecas de desenvolvimento do X e da OpenGL, libogg, libvorbis, libmng. Outras já possuem seus pacotes prontinhos para serem instaladas, são elas:

Jam: http://www.slacky.eu/aadm/pkgs/index.php?ver=6&pkg=658
wxWidgets 2.8.10: http://www.slacky.eu/aadm/pkgs/index.php?ver=6&pkg=1165
libmspack: http://www.slacky.eu/aadm/pkgs/index.php?ver=6&pkg=792 (dependência da wxWidgets acima)
CEGUI 0.6.2: http://www.slacky.eu/aadm/pkgs/index.php?ver=6&pkg=635

Outros possuem SlackBuild's prontos:

ODE 0.8: http://slackbuilds.org/repository/12.1/libraries/ode/ (utilizei a versão para o Slack 12.1 e que funciona muito bem no 12.2, pois esta é a versão recomendada para a CS). Aqui está o link para o pacote que compilei: ode-0.8-i486-1_SBo.tgz

Não instalei algumas dependências, pois não pretendo utilizar, sendo ela a biblioteca Bullet, pois pretendo utilizar a ODE.

Estas bibliotecas compilei utilizando o pkgcreate:

cal3d-0.11.0-i686-1_PKGC.tgz
lib3ds-1.3.0-i686-1_PKGC.tgz
libcaca-0.99.beta13-i686-1_PKGC.tgz (o pacote oficial do Slack deve ser substituído por este, pois esta versão é requerida, porém tal biblioteca é opcional, sendo apenas necessária se você quiser a saída do seu programa em ASCII :-)

Binários da Cg Toolkit podem ser encontrados no site http://developer.nvidia.com/object/cg_toolkit.html. Aqui instalei a versão 2.1, porém a partir do site da CS, qualquer versão acima da 1.4 deve funcionar.

Muito bem, depois de instalado todos esses arquivos, basta compilar a CS. Baixe os fontes através do comando:

svn co https://crystal.svn.sourceforge.net/svnroot/crystal/CS/branches/release/V1.4 CS_1.4

Agora vá tomar um café enquanto os fontes são baixados. Depois disso, acesse o diretório criado e agora digite ./configure e make ou jam (neste caso o make é uma capa para o jam). E vá tomar outro café :-). Após alguns minutos ou horas, dependendo da sua máquina você estará com a CS compiladinha :D. Não irei dizer para você instalar a biblioteca, pois tive problemas ao fazer isso, o sistema de detecção de colisões não funcionou corretamente, então utilize a biblioteca a partir do local onde esta está.

Vamos partir para a CEL agora, que é uma biblioteca de entidades construída sobre a CS que pode ser considerada uma engine para jogos. Assim como a CS, as informações para compilar e instalar a CEL também estão disponíveis online: http://crystalspace3d.org/cel/docs/online/manual-1.2/Building.html#0. Tais informações não são muito completas, mas já é melhor do que nada.

Esta é bem mais fácil para compilar, já que não exige a instalação de muitas dependências, pois python é padrão em qualquer distribuição. Além desta existe um pacote opcional, o HawkNL, caso você queira suporte a redes, o que eu acho uma ótima idéia. Para esta dependência eu não encontrei pacotes e também não consegui gerar o pacote através do pkgcreate e também fui preguiçoso o suficiente para apenas compilá-la e instalá-la, sem criar pacote algum. O site da HawkNL é http://www.hawksoft.com/hawknl/. Outra coisa importante é exportar a variável CRYSTAL com o caminho onde você compilou a CS.

Pronto, feito isso basta rodar o comando "jam" e ir tomar um café. Após isso você já pode utilizar a biblioteca para criar seus próprios programas assim como rodar os vários exemplos que vem com ela. Para rodar os exemplos você deve exportar a variável LD_LIBRARY_PATH para apontar para onde você compilou a CS.