Vou-me embora para Pasárgada

Vou-me embora para Pasárgada
Lá sou amigo do Reis

Novidades:

1 - Estou formado em Ciência da Computação pela UFPR.

2 - Estou deixando Curitiba. Após 22 anos na saudosa Curitiba estou deixando-a, e indo para Recife-PE.

Só tenho o que agradecer a esta magnífica cidade, à minha família que fica por aqui, e aos meus colegas da Mandriva, com os quais pude aprender bastante.

E esperar que este novo desafio seja tão bom e gratificante quanto o antigo.

Auto-completar no python do Mac OsX

Certa vez o Ademar comentou que o python tinha auto-completar por padrão. Pessoalmente nunca tinha percebido isto, e conversando com o Ramiro percebi o porquê: Mac OS X e Windows não inicializam os módulos readline e o rlcompleter sozinhos.

Procurando um pouco vi que habilitá-los é fácil.

Primeiro edite o arquivo ~/.pythonrc

#Enable syntax completion
try:
    import readline
except ImportError:
    print "Module readline not available."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")

Após isto, em seu ~/.bashrc adicione:

export PYTHONSTARTUP=~/.pythonrc

Agora inicie o python e faça o teste.

Hello world para Native-Symbian

Certa vez eu quis explicar a um amigo porque escrever código em python para celular era mais legal que escrever código em C (native-symbian e não OpenC). Acho que hoje talvez eu consiga.

Segue os exemplos:

Python

print “Hello World”

C++-Epoc

// Hello World in C++, Epoc style (for Symbian OS)
#include < eikapp.h >
#include < eikdoc.h >
#include < eikappui.h >

class CHelloWorldAppUi;
class CEikApplication;
class CHelloWorldAppView;

class CHelloWorldApplication : public CEikApplication
{
public:
TUid AppDllUid() const;
protected:
CApaDocument* CreateDocumentL();
};

class CHelloWorldDocument : public CEikDocument
{
public:
static CHelloWorldDocument* NewL(CEikApplication& aApp);
static CHelloWorldDocument* NewLC(CEikApplication& aApp);
~CHelloWorldDocument(){};
public:
CEikAppUi* CreateAppUiL();
private:
void ConstructL() {};
CHelloWorldDocument(CEikApplication& aApp){};
};

class CHelloWorldAppUi : public CEikAppUi
{
public:
void ConstructL();
CHelloWorldAppUi(){};
~CHelloWorldAppUi(){};
};

static const TUid KUidHelloWorldApp = {0×10005B91};

GLDEF_C TInt E32Dll(TDllReason )
{
return KErrNone;
}

EXPORT_C CApaApplication* NewApplication()
{
return (new CHelloWorldApplication);
}

CApaDocument* CHelloWorldApplication::CreateDocumentL()
{
CApaDocument* document = CHelloWorldDocument::NewL(*this);
return document;
}

TUid CHelloWorldApplication::AppDllUid() const
{
return KUidHelloWorldApp;
}

CHelloWorldDocument* CHelloWorldDocument::NewL(CEikApplication& aApp)
{
CHelloWorldDocument* self = NewLC(aApp);
CleanupStack::Pop(self);
return self;
}

CHelloWorldDocument* CHelloWorldDocument::NewLC(CEikApplication& aApp)
{
CHelloWorldDocument* self = new (ELeave) CHelloWorldDocument(aApp);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}

CEikAppUi* CHelloWorldDocument::CreateAppUiL()
{
CEikAppUi* appUi = new (ELeave) CHelloWorldAppUi;
return appUi;
}

void CHelloWorldAppUi::ConstructL()
{
BaseConstructL();

_LIT(message,”Hello!”);
CAknInformationNote* informationNote = new (ELeave) CAknInformationNote;
informationNote->ExecuteLD(message);
}

fonte: http://www.roesler-ac.de/wolfram/hello.htm

Pychord 2 saindo do forno

Certa vez um colega de trabalho de uma das empresas por onde passei comentou:

“Não basta colocar um filho no mundo, é preciso alimenta-lo, educa-lo e fazer o possível para vê-lo crescido!”

Pois bem, depois de certo tempo resolvi voltar a mexer no abandonado código do pychord e adicionar algumas funcionalidades que eu precisava.

Após duas tentativas frustradas (0.4.5 e 0.5) percebi que era necessário re-escrever a biblioteca gráfica. Assim foi feito. Adicionei o conceito de janela, conteiner de widgets, melhorei a herança entre classes, etc. A interface não mudou muita coisa, pygame é meio chato para isso.

Ainda estou usando o padrão .chr criado para a primeira versão, mas pretendo adicionar o formato XML opensong em breve.

A parte legal, e a novidade mais visível, é que criei uma heurística para decidir quais linhas são acordes e quais não são. Esta heurística pretendo ir melhorando a medida que for encontrando casos em que ela não funcione.

Para resumir: ao nível de usuário, as modificações foram:

  1. Heurística para reconhecer/diferenciar acordes de letra de músicas
  2. Mudança de tom
  3. Listas clicáveis e móveis
  4. Suporte ao Maemo OS2008
  5. Controle da luminosidade durante a apesentação das cifras ( o display não apaga durante a mostragem mais )

A parte nerd

A idéia era que o código da interface pudesse ser reutilizada em outros projetos, logo trabalhei para ter uma GUI mais conscistente do que a anterior. Utilizando melhor o conceito de herança foi possível simplificar a utilização da lib, deixando as coisas com menos cara de gambiarra.

Através do conceito de slots ficou bem simples implementar mais de uma action para um mesmo evento.

Screenshots

Pychord-screenshot

Tela de busca, não mudou muito de como era anteriormente.

Pychord-screenshot2

Visualização da cifra

Pychord-Screenshot3

Mudaça de tom.

Como sempre, o arquivo de instalação pode ser pego aqui. Ainda não criei um repositório pois o aplicativo está em fase de testes. Mas pretendo fazer isto em breve.

[UPDATE 03/03/2008] Por problemas de codificação dentro do módulo sqlite3, os textos devem estar em formato UTF-8…

PyChord First Release Candidate. Pegue seu .install aqui!

Finalmente, Pychord está pronto!

Todas as features (da versão 1.0) ja estão funcionando. Agora eu preciso trabalhar em duas linhas diferentes:

[1] Eu não tinha conhecimento suficiente sobre pygame quando iniciei este projeto. Então eu preciso alterar algumas partes do código para corrigir decisões erradas de engenharia que tomei anteriormente.
[2] Se você for utilizar esta aplicação, por favor, dê-me um feedback e eu vou tentar melhorá-la!

Depois disto eu vou iniciar a versão 1.1 ( com as features que prometi anteriormente ).

Caso você precise de informações sobre como utilizar o programa, leia isto.

Você pode fazer o download do “.install” aqui!

Se você tiver problemas para instalar esta aplicação, tente novamente procurando por pychord em

ApplicationManager->Browse Installable Applications->others->pychord

Se após isto você ainda tiver problemas (ou sugestões), por favor, reporte!

[]’s

Pychord: minha primeira contribuição ao Maemo.

Estou dando vida à minha primeira contribuição opensource ao projeto Maemo.

É o Pychord.

PyChord é uma aplicação que ajudará músicos durante ensaios mostrando cifras das músicas. A vantagem é que ele possui função de auto-scroll da tela, além de ter botões relativamente grandes.

Bastará ao usuário procurar pelo nome da música e o sistema mostrará a cifra. Como passei muito tempo brincando com a interface dele (fazer widgets no pygame parecia impossível antes, além do scroll sensível e com impulso), acabou não dando tempo de desenvolver a interface de busca por cifras. Mas estou pensando em usar o SQLite mesmo. De qualquer forma, além da search engine tem algumas features que pretendo desenvolver pra ele:

  1. Troca de tom das músicas (muito útil pra caras como eu que custam para lembrar que a diferença entre B e C é de meio tom)
  2. Rotação da tela.

De qualquer forma, tenho que agradecer ao Tony Maro que desenvolveu o teclado virtual e ao Marcelo ao dizer que não é bonito scroll-bars aonde não precisa. =)

O código não está aquela beleza, mas vai ter feriado por aí e eu vou ter bastante tempo livre para arrumar e terminar a aplicação.

Meu inglês não é lá essas coisas, mas fiz um vídeo de demonstração da aplicação que pode ser visto abaixo.

Com isto estou criando uma versão do meu blog na língua da rainha: http://labs.danilocesar.com.

E para quem quiser ver o código do PyChord:

svn co http://labs.danilocesar.com/pychord/trunk

Aceito sugestões!

[]’s a todos e bom feriado!

Gdesklets, um pouco mais que o basicão

Hoje vou apresentar o aplicativo Gdesklets.

Para quem não sabe, este aplicativo permite que o usuário rode pequenas aplicações “applets” diretamente no desktop. Possui por padrão vários applets prontos, como relógios, monitores de desempenho de hardware, previsão do tempo, entre outras coisas. Segue uma screenshot do meu desktop:

Gdesklets Desktop

Tá tá! Você usuário linux mediano provavelmente já saiba disso: Já conhecia o Gdesklets, e muito provavelmente também já usava, certo? Então o que esse post tem de diferente?

Como desenvolver seus próprios Applets

Para iniciar, digo que é muito fácil desenvolver aplicativos para o Gdesklet. Para quem está acostumado com HTML, vai lembrar de alguns conceitos como posicionamento, tags, ID’s, etc…

O que vou passar aqui pra vocês é o que eu aprendi sobre gdesklets nesta semana.

Cada parte do Gdesklets

Cada applet consiste em:

  • Uma janela, definida em um arquivo.display, que é, na verdade, um xml.
  • Um sensor, que é responsável por controlar e retornar dados para o display

Primeiros Passos com o Display

Inicialmente vamos chamar nosso aplicativo de PrimeirosPassos (Sugestivo não?)
Crie uma pasta com ~/mkdir .gdesklets/Displays/PrimeirosPassos

Dentro desta pasta, crie um arquivo chamado PrimeirosPassos.display com o seguinte conteúdo

  1. < ?xml version=“1.0″ encoding=“UTF-8″ ?>
  2.     <display id=“WPrimeirosPassos”>
  3.     </display>

E esta aí a estrutura básica de um Display no Gdesklets. Resumidamente, tudo o que você quiser colocar na sua tela você deverá colocar dentro da Tag display

Para incrementar um pouco mais, vamos fazer o clássico HelloWorld

  1. < ?xml version=“1.0″ encoding=“UTF-8″?>
  2.  
  3. <display id=“WPrimeirosPassos”>
  4.     <label value=“HelloWorld com GDesklets!” font=“Serif 20″ color=“red”/>           
  5. </display>

Aprendemos então uma nova Tag no Desklet: A Tag Label, que possui as seguintes propriedades:

color, Permite escolher a cor

font, Permite escolher a fonte

value, Define o conteúdo que o label terá na tela.

Agora vamos ver como o Desklet aparece na tela.
Ola mundo em gdesklets

Agrupamentos

Na estrutura XML do Desklet, existe também a TAG Group, que é utilizada para agruar elementos da estrutura. Um exemplo seria:

  1. <group x=“20″ y=“20″ bg-color=“green”>
  2.         <label x=“0″ y=“0″ value=“#2″/>
  3.         <label x=“0″ y=“50″ value=“#3″/>
  4.         <label x=“50″ y=“0″ value=“#4″/>
  5. </group>

Dentro da tag group, vemos também as propriedades X e Y, que logicamente definem o posicionamento X Y do elemento na tela.

Posicionamento relativo e âncoras

A estrutura desklet permite a existencia do chamado posicionamento relativo.
Posicionamento relativo nada mais é do que o posicionamento XY relativo ao um outro objeto

Por exemplo: o usuário quer que o segundo elemento label fique ao lado do primeiro elemento:

  1. <label font=“Sans 14px” color=“white” id=“label1″ value=“Ola “ />
  2.     <label relative-to=“label1, x” font=“Sans 14px” color=“green” value=“Mundo”/>

A propriedade relative-to dos elementos recebem dois parametros: O primeiro é o Identificador do objetivo, e o segundo é a que propriedade queremos esta relatividade. Este valor pode ser X, Y ou XY.

Podemos também definir aonde queremos esta relatividade através da propriedade anchor. O valor default é NW (superior esquerdo). Os outros valores são:

  • nw - Topo esquerdo
  • n - Meio do topo
  • ne - Topo Direito
  • e - Meio do canto direito
  • se - Canto inferior direito
  • s - Meio de baixo
  • sw -Canto inferior esquerdo
  • w - Meio da lateral direita
  • center - Centro

Fase dois

Bem, precisamos de uma aplicação descente para fazermos nossos testes, certo? Como não quero fazer um applet de previsão do tempo (pois já existem muitos), resolvi fazer um para receber dados de ações diretamente da Bovespa! O nome do projeto será Bovespa (lembre-se de utlizar o nome das pastas como Bovespa).

Interface

O código da interface é o seguinte:

  1. < ?xml version=“1.0″ encoding=“UTF-8″?>
  2.  
  3. <display id=“win” anchor=“ne” window-flags=“sticky, below”>
  4.  
  5.     <sensor id=“sens” module=“Bovespa,posi3″/>
  6.  
  7.     <meta name=“Bovespa” version=“0.01″ category=“Misc” author=“Danilo Cesar” description=“Bovespa’s Home Broker utility “/>
  8.               
  9.     <frame id=“border”>
  10.         <group id=“panel” width=“5cm” height=“2,5cm”>
  11.             </group><group id=“Titleobjs” width=“100%”>
  12.                 <image id=“logo” x=“2″ y=“2″ uri=“/usr/share/icons/gnome/48×48/stock/document/stock_new-spreadsheet.png”/>
  13.                 <label relative-to=“logo,x” x=“1cm” id=“title” value=“Bovespa” font=“Sans 20px” color=“black”/>
  14.                 <label anchor=“se” relative-to=“title,xy” y=“.6cm” watch=“value=sens:nome” value=“Carregando” font=“Sans 20px” color=“white”/>
  15.             </group>
  16.             <group id=“values” width=“100%” relative-to=“Titleobjs, y”>
  17.                 <label font=“Sans 14px” color=“white” id=“lblo” value=“Oscilacao: “ />
  18.                 <label relative-to=“lblo, x” watch=“value=sens:oscilacao, color=sens:color” font=“Sans 14px” color=“green” value=“carregando”/>
  19.                 <label relative-to=“lblo, y” font=“Sans 14px” color=“white” id=“lblp” value=“Preço:        “ />
  20.                 <label relative-to=“lblp, x” watch=“value=sens:price, color=sens:color” font=“Sans 14px” color=“green” value=“carregando”/>
  21.             </group>
  22.        
  23.     </frame>
  24. </display>

Aqui nós temos duas coisas novas:
A primeira é a tag sensor, que possui 2 argumentos:
id: Que será como o sensor será referenciado pelo display.
module: Que define qual sensor deverá ser utilizado. Queremos o sensor Bovespa, e seu argumento será posi3 (código da positivo informática na Bolsa de São Paulo).

A outra informação nova é parâmetro watch nos labels, que é um receptor de dados do sensor. Vamos dar um exemplo:

<label watch=”color=sens:cor”
Significa que o parâmetro Color do Label será preenchido pela propriedade “cor” do sensor “sens”. Simples não?

Programação do sensor

Os sensores são arquivos criados com o nome __init__.py. No caso do nosso exemplo, criemos um arquivo chamado: ~/.gdesklets/Sensors/Bovespa/__init__.py . O arquivo mais básico para um sensor deve conter pelo menos o seguinte conteúdo:

  1. from sensor.Sensor import Sensor
  2.  
  3.  
  4. class Bovespa(Sensor):
  5.     def __init__(self, *args):
  6.         Sensor.__init__(self)
  7.  
  8. def new_sensor(args): return Bovespa(*args)

A Classe Bovespa extende a classe sensor, por isso dentro dela podemos chamar algumas funções especiais. Listo algumas abaixo:

self._add_timer(tempo,funcao,parametros) nos permite executar uma função funcao e seus paremetros a cada tempo milisegundos. A função executada deverá retornar sempre true,e caso retorne false, a função deixará de ser executada.

output = self._new_output() cria uma porta de saída para o display. É a forma que o python tem de enviar seus dados para o display. O objeto output possui um método importante: output.set(‘nome’, ‘valor’), que grava o argumento ‘nome’ com o valor ‘nome’.

self._send_output(output), que é o método responsável em enviar uma lista de output’s para o display.

Com estes conhecimentos poderemos agora desenvolver nosso sensor. Que ficará da seguinte forma:

  1. from sensor.Sensor import Sensor
  2. from utils.datatypes import *
  3. import re
  4. import urllib
  5.  
  6. class Bovespa(Sensor):
  7.  
  8.     def __init__(self, acoes = ‘posi3′):
  9.  
  10.                 # call the constructor of the super class
  11.         Sensor.__init__(self)
  12.        
  13.         self.acoes = acoes[0]
  14.        
  15.         # Atualização do tipo ONLOAD, que ocorre apenas
  16.         # uma vez pois retorna um False
  17.         self._add_timer(0, self.refresh, False)
  18.  
  19.         # Atualizações do sistema a cada 60 segundos
  20.         self._add_timer(60000, self.refresh, True)
  21.  
  22.    
  23.     def refresh(self, FT):
  24.        
  25.         f = urllib.urlopen (‘http://www.bovespa.com.br/Cotacoes2000/CotacaoRapidaHome.Asp?PaginaReferente=home_right.Asp&txtCodigo=’ +self.acoes)
  26.         self._text = contents = f.read()
  27.         f.close()
  28.        
  29.         self._text = self._text.replace(‘&nbsp;’, ‘ ‘)
  30.  
  31.         # Definindo variáveis para enviar ao Display
  32.         output = self._new_output()
  33.         output.set(‘nome’, self.acoes.upper())
  34.         output.set(‘oscilacao’, self.get_oscilacao())
  35.         output.set(‘price’, self.get_price())
  36.         output.set(‘color’, self.get_color())
  37.        
  38.        
  39.         self._send_output(output)
  40.  
  41.         return FT
  42.  
  43.         # Procura por expressao regular a string com o preco da acao
  44.     def get_price(self):
  45.         ips = re.search(‘R\$ [0-9][0-9]{0,3},[0-9]{1,2}’,self._text)
  46.         if ips <> None:
  47.             return ips.group(0)
  48.         else:
  49.             return ‘Erro!’
  50.     #Procura por ER a string com a ascilacao da acao
  51.     def get_oscilacao(self):
  52.         ips = re.search(‘(-|\+)?[0-9][0-9]?,[0-9][0-9]%’,self._text)
  53.         if ips <> None:
  54.             return ips.group(0)
  55.         else:
  56.             return ‘Erro!’
  57.         # Escolhe a cor para mostrar a acao.
  58.         # Vermelhor para erro ou acao negativa
  59.         # verde para acao positiva
  60.     def get_color(self):
  61.         ips = self.get_oscilacao();
  62.         if (ips[0] == ‘-’ or ips == ‘Erro!’):
  63.             return ‘red’
  64.         else:
  65.             return ‘green’
  66.            
  67.            
  68. def new_sensor(args): return Bovespa(args)

Nosso applet ficará assim:
Aplicativo Bovespa

Não citei como fazer as seções de configuração e algumas outras coisas porque também ainda não tive tempo de ver.
Aos interessados, podem fazer aqui o download completo do applet Bovespa aqui

Alguns links interessantes são:

E é isso. Espero que vocês tenham boa sorte com seus applets, e melhor sorte do que eu em suas ações!

Smartphones: aonde podemos parar?

Tive o prazer de ter em minhas mãos um Nokia 6681 a alguns dias atrás, e tive uma idéia:

Imagine uma touchscreen. Agora imagine uma touchscreen sem uma touch-screen =).
Imagine poder “simular” uma touchscreen no ar usando apenas a camera do seu celular.

Pode ser um brinquedo muito interessante não?

Pensando nisso fiz um pequeno aplicativo em Python (pyS60) que localiza um objeto e segue-o. Como se fosse um mouse pointer seguindo uma caneta.

Este aplicativo na verdade é apenas uma prova de conceito demonstrando que pode ser feito. Quando tivermos celulares melhores, algo como 1GHz (O 6681 possui um processador de 220Mhz), e cameras próprias para este tipo de aplicação, talvez tenhamos softwares e smartphones com este conceito em funcionamento.
Seria muito bacana ver soluções assim aplicadas em desktops 3D.

Segue um vídeo de demonstração do aplicativo. Como disse, é apenas uma prova de conceito. Python ainda não é uma linguagem muito rápida quando estamos em celulares. Mas é muito mais fácil programar e testar do que se fosse feito em native symbian, e ainda por cima posso programar em linux =).

Leitores de RSS podem ver o vídeo aqui

Código fonte

  1. ##############################################
  2. # Produzido por Danilo Cesar [http://www.danilocesar.com]
  3. # Inspirado por:  http://www.bigbold.com/snippets/posts/show/636
  4. # Agradecimento a Enrico Batista
  5. ##############################################
  6. from appuifw import *
  7. from graphics import Image
  8. import camera, e32
  9. #import miso    # don’t dim the light
  10.  
  11. app.body = c = Canvas()
  12.  
  13. running = 1
  14. def quit():
  15.     global running
  16.     running = 0
  17.  
  18. app.exit_key_handler=quit
  19. app.title = u“O controle”
  20. app.screen = ‘full’   # or ‘normal’, ‘large’
  21.  
  22. def getdata(im, bpp=24):
  23.     import struct, zlib
  24.     im.save(‘D:\\pixels.png’, bpp=bpp, compression=‘no’)
  25.     f = open(‘D:\\pixels.png’, ‘rb’)
  26.     f.seek(8 +8+13+4)
  27.     chunk = []
  28.     while 1:
  29.         n = struct.unpack(‘>L’, f.read(4))[0]
  30.         if n==0: break  # ‘IEND’ chunk
  31.         f.read(4) # ‘IDAT’
  32.         chunk.append(f.read(n))
  33.         f.read(4)   # CRC
  34.     f.close()
  35.     return zlib.decompress(.join(chunk))  # ‘\x00′ prefix each line
  36.  
  37.  
  38. X = 80
  39. Y = 60
  40. while running:
  41.     if X < 0: X = 0
  42.     if Y< 0: Y = 0
  43.     if X > 160 - 30: X = 160 - 30
  44.     if Y > 120 - 30: Y = 120-30
  45.     im = camera.take_photo(‘RGB’, (160,120))
  46.     im.rectangle([(X,Y),(X+30,Y+30)], 0xff0000)   # red outline
  47.     # check hot spot whether active
  48.     box = Image.new((30,30), ‘L’)  # gray scale
  49.     box.blit(im, (X,Y,X+30,Y+30))
  50.     data = getdata(box, 8)
  51.  
  52.     # check black
  53.     for i in range(len(data)):
  54.         if ord(data[i]) < 30 and ord(data[i]) > 0:
  55.             X += i%31 - 15
  56.             Y += int(i/31) - 15
  57.             break
  58.         # Posso passar de 3 em 3 pixels. O código fica mais rápido e a perda
  59.         # de precisão é insignificante
  60.         i = i + 2
  61.  
  62.     c.blit(im, (0,0), (8,12))   # show camera
  63.  
  64.     #miso.reset_inactivity_time()
  65.  

Python for S60… Programar celulares nunca foi tão fácil!

A alguns dias atrás estava procurando outros métodos de programação para celulares…

Eu já conhecia o famoso J2ME (JAVA micro edition), também já conhecia o Native Symbian C++. Mas procurava algo mais dinâmico… Mais prático….

Numa viagem que fiz pra londrina, brincando com meu celular (Nokia 6600) começei a pensar em como seria útil uma linguagem rodando por script, pra realizar tarefas simples, como por exemplo o BASH no linux….. Foi ai que eu conheci o Python for S60.

Pra começar: Porque Python?
Pythonis a simple, consistent and effective programming language. [Manual Getting Started With Pyton]

(more…)