Do YouTube para o Smartphone – Parte 1

Conversando com um amigo sobre desenvolvimento de software, desenvolvimento dirigido a testes,integração contínua, entre outras coisas, veio a vontade de automatizar um processo de extração de mp3 de vídeos do Youtube e depois enviar o arquivo do notebook para o smartphone, a fim de ouvi-lo com um aplicativo para podcasts.

Até agora não escrevi nada, tão pouco pesquisei profundamente sobre as bibliotecas e ferramentas necessárias. Vou explicar aqui apenas as ideias que tenho no momento.

Problema

Eu tenho pouco tempo para assistir vídeos mas tenho conseguido ouvir meus podcasts favoritos. Por isso, para continuar consumindo alguns canais do Youtube, estou extraindo o mp3 dos vídeos para ouvir no smartphone. Depois eu jogo esses arquivos no Dropbox ou diretamente do smartphone via USB. O aplicativo para ouvir podcasts que uso atualmente é Podcast Addict. Eu trato uma pasta como um fonte de podcasts.

Módulo Desktop

Eu tenho um notebook Dell rodando a última versão do Ubuntu no momento da edição desse post.

Atualmente uso o programa de linha de comando youtube-dl para extrair o mp3 dos vídeos do Youtube.

Minha ideia é escrever um programa que acesse os canais do Youtube que consumo e verifique se há novos vídeos. Gostaria aqui de usar a API do Twitter para me enviar uma mensagem privada me perguntando se eu gostaria do mp3 do vídeo. Eu responderia por mensagem, igualmente, um sim ou um não.

Se a resposta for sim, o programa executaria o youtube-dl e jogaria o arquivo para uma determinada pasta do Dropbox.

Módulo Smartphone

Eu tenho um smartphone Quantum Go rodando Android Lollipop no momento da edição desse post.

Do lado do smartphone, basta ter o Dropbox instalado e uma de suas pastas servindo como fonte de podcasts do Podcast Addict. Terei de pesquisar se o Addict conseguirá acessar o mp3, uma vez que no dispositivo móvel o download é sob demanda.

Nos próximos posts, continuaremos a tratar desse assunto com o resultado de pesquisas e códigos.

MaginBook sem a infra do Lackey

Mudei de idéia em relação a usar a infraestrutura do LackeyCCG.

Optei por implementar um plugin que dado uma lista de siglas de sets de Magic, acesse um site e carregue as informações dos cards, gravando-as num banco de dado SQLite. Foi uma escolha mais divertida.

Outra vez a biblioteca BeautifulSoup foi incrível. Navegar na árvore de tags HTML e extrair os dados é moleza com ela.

DiceDnd 1.1

Depois de um final de semana complicado e acamado, voltei a escrever na segunda-feira os melhoramentos do DiceDnd. Pretendia melhorar o visual, habilitar o modo fullscreen e ainda fazer um pacote debian para distribuir o programa. Devido às dificuldades encontradas, fiquei somente no melhoramento visual. Pois bem, tirei umas fotos do aplicativo funcionando (não descobri uma função print screen no N800) e ainda estou disponibilizando uma nova versão abaixo.

Vou ficar devendo o fullscreen e o pacote.

DiceDnd no Nokia N800
DiceDnd no Nokia N800
DiceDnD com o resultado da jogada de dados
DiceDnD com o resultado da jogada de dados

fonte do dicednd.py (atualizado)

#!/usr/bin/python2.5

import osso
import gtk
import hildon

def labela(texto):
    fonte = '%s'
    etiqueta = gtk.Label(fonte % texto)
    etiqueta.set_use_markup(True)
    return etiqueta

def string_jogada(vezes, dado, soma):
    if soma > 0:
        sinal = '+'
    elif soma == 0:
        sinal = ''
    else:
        sinal = '-'
    return '%dd%d%s%s' % (vezes, dado, sinal, abs(soma) or '')

class DiceDnD(hildon.Program):
    def __init__(self):
        self.dado_atual = 0
        self.vezes = 0
        self.soma = 0
        hildon.Program.__init__(self)
        self.window = hildon.Window()
        self.window.set_title('DiceDnd')
        self.window.set_border_width(40)
        self.window.connect("destroy", self.quit)
        self.add_window(self.window)

        tabela = gtk.Table(5,4,False)
        self.window.add(tabela)        

        self.dado4 = gtk.Button()
        self.dado4.add(labela('4'))
        self.dado6 = gtk.Button()
        self.dado6.add(labela('6'))
        self.dado8 = gtk.Button()
        self.dado8.add(labela('8'))
        self.dado10 = gtk.Button()
        self.dado10.add(labela('10'))
        self.dado12 = gtk.Button()
        self.dado12.add(labela('12'))
        self.dado20 = gtk.Button()
        self.dado20.add(labela('20'))
        self.botaoMais = gtk.Button()
        self.botaoMais.add(labela('+'))
        self.botaoMenos = gtk.Button()
        self.botaoMenos.add(labela('-'))
        self.botaoJogar = gtk.Button()
        self.botaoJogar.add(labela('Jogar'))
        self.frame = gtk.Frame()
        self.montagem = gtk.Label('Jogada')
        self.frame.add(self.montagem)
        
        tabela.attach(self.dado4,0,1,0,1)
        tabela.attach(self.dado6,1,2,0,1)
        tabela.attach(self.dado8,2,3,0,1)
        tabela.attach(self.dado10,0,1,1,2)
        tabela.attach(self.dado12,1,2,1,2)
        tabela.attach(self.dado20,2,3,1,2)
        tabela.attach(self.botaoMais,0,1,2,3)
        tabela.attach(self.botaoJogar,1,2,2,3)
        tabela.attach(self.botaoMenos,2,3,2,3)
        tabela.attach(self.frame,0, 3, 3, 4)
        
        self.dado4.connect('clicked',self.preparar,4)
        self.dado6.connect('clicked',self.preparar,6)
        self.dado8.connect('clicked',self.preparar,8)
        self.dado10.connect('clicked',self.preparar,10)
        self.dado12.connect('clicked',self.preparar,12)
        self.dado20.connect('clicked',self.preparar,20)
        self.botaoMais.connect('clicked',self.incrementar,1)
        self.botaoMenos.connect('clicked',self.incrementar,-1)
        self.botaoJogar.connect('clicked',self.mostrar)
        
        self.window.show_all()
        
    def mostrar(self, button):
        if self.dado_atual == 0:
            return
        import random
        total = 0
        for i in range(self.vezes):
            total += random.randint(1,self.dado_atual)
        total = total + self.soma
        jogada = string_jogada(self.vezes, self.dado_atual, self.soma)
        self.show_message('%s' % total)

    def preparar(self, button,valor):
        if valor  self.dado_atual:
            self.dado_atual = valor
            self.vezes = 1
            self.soma = 0
        else:
            self.vezes += 1
        self.montagem.set_text(string_jogada(self.vezes, self.dado_atual, self.soma))
            
    def incrementar(self, button,valor):
        self.soma = self.soma + valor
        self.montagem.set_text(string_jogada(self.vezes, self.dado_atual, self.soma))


    def show_message(self, message):
        dlg = hildon.Note('information', (self.window, message))
        dlg.run()
        dlg.destroy()
        #pango_markup = '%s\n%s' % ('DiceDnD', message)
        #hildon.hildon_banner_show_information_with_markup(gtk.Label(''), None, pango_markup)

    def quit(self, evt):
        gtk.main_quit()
        
    def run(self):
        gtk.main()

def main():
    prog = DiceDnD()
    prog.run()

if __name__ == "__main__":
    main()

DiceDnd

Os dados usados no RPG D&D
Os dados usados no RPG D&D

A minha idéia exploratória de criar um aplicativo para gerar jogada de dados no meu N800  ocupou umas horas da noite de sexta e início de madrugada do sábado.

O objetivo da aplicação é bem simples. Eu vou voltar a mestrar campanhas de RPG. Comprei o recente D&D 4ª Edição em português mais uma aventura para personagens iniciantes. Não tenho todos os tipos de dados necessários. São 6 tipos, por quantidade de faces: 4, 6, 8, 10, 12 e 20. Assim, queria simular a parada de dados pelo meu N800, um internet tablet da Nokia.

Uma das principais linguagens para programar nesses dispositivos é Python. Apesar de não conhecer muito a biblioteca Gtk (biblioteca gráfica), conheço a linguagem razoavelmente bem, por isso acreditava que conseguiria implementar o aplicativo no final de semana.

A primeira providência foi procurar documentação. A idéia do projeto já estava toda na minha cabeça mas não sabia por onde começar. Depois de um tempo, encontrei algumas coisas. Foram importantes os seguintes documentos:

A versão do sistema operacional é o OS 2008 (Diablo). O Python 2.5 já estava instalado. De fato, não precisei instalar outra coisa. Algumas documentações diziam que eu tinha de instalar o interpretador da linguagem. Talvez eu tenha feito isso algum tempo atrás.

Outra coisa que ajudou bastante, para ir escrevendo e testando rapidamente, foi acessar via SSH o dispositivo pelo Nautilus (num notebook com Ubuntu). Criei o arquivo da aplicação no cartão do N800 e depois abrir com o editor TextFlow. Daí era só escrever, salvar e ir no PDA executar a aplicação.

O cliente e servidor do SSH não vem instalado por default no N800. Nem o terminal. Por ele é que eu rodava o Python. Pelo notebook, eu usava também um terminal para acessar o N800 via ssh. Era útil para testar algumas coisas no interpretador interativo do Python.

As próximas tarefas envolvem melhorar o aspecto visual da aplicação e preparar um instalador para ficar mais fácil de dispobilizar. O código-fonte encontra-se abaixo:

#!/usr/bin/python2.5

import osso
import gtk
import hildon

def string_jogada(vezes, dado, soma):
    if soma > 0:
        sinal = '+'
    elif soma == 0:
        sinal = ''
    else:
        sinal = '-'
    return '%dd%d%s%s' % (vezes, dado, sinal, abs(soma) or '')

class DiceDnD(hildon.Program):
    def __init__(self):
        self.dado_atual = 0
        self.vezes = 0
        self.soma = 0
        hildon.Program.__init__(self)
        self.window = hildon.Window()
        self.window.set_title('DiceDnd')
        self.window.connect("destroy", self.quit)
        self.add_window(self.window)

        tabela = gtk.Table(5,4,True)
        self.window.add(tabela)

        self.dado4 = gtk.Button('4')
        self.dado6 = gtk.Button('6')
        self.dado8 = gtk.Button('8')
        self.dado10 = gtk.Button('10')
        self.dado12 = gtk.Button('12')
        self.dado20 = gtk.Button('20')
        self.botaoMais = gtk.Button('+')
        self.botaoMenos = gtk.Button('-')
        self.botaoJogar = gtk.Button('Jogar')
        self.frame = gtk.Frame()
        self.montagem = gtk.Label('Jogada')
        self.frame.add(self.montagem)

        tabela.attach(self.dado4,0,1,0,1)
        tabela.attach(self.dado6,1,2,0,1)
        tabela.attach(self.dado8,2,3,0,1)
        tabela.attach(self.dado10,0,1,1,2)
        tabela.attach(self.dado12,1,2,1,2)
        tabela.attach(self.dado20,2,3,1,2)
        tabela.attach(self.botaoMais,0,1,2,3)
        tabela.attach(self.botaoJogar,1,2,2,3)
        tabela.attach(self.botaoMenos,2,3,2,3)
        tabela.attach(self.frame,0, 3, 3, 4)

        self.dado4.connect('clicked',self.preparar,4)
        self.dado6.connect('clicked',self.preparar,6)
        self.dado8.connect('clicked',self.preparar,8)
        self.dado10.connect('clicked',self.preparar,10)
        self.dado12.connect('clicked',self.preparar,12)
        self.dado20.connect('clicked',self.preparar,20)
        self.botaoMais.connect('clicked',self.incrementar,1)
        self.botaoMenos.connect('clicked',self.incrementar,-1)
        self.botaoJogar.connect('clicked',self.mostrar)

        self.window.show_all()

    def mostrar(self, button):
        if self.dado_atual == 0:
            return
        import random
        total = 0
        for i in range(self.vezes):
            total += random.randint(1,self.dado_atual)
        total = total + self.soma
        jogada = string_jogada(self.vezes, self.dado_atual, self.soma)
        self.show_message('%s' % total)

    def preparar(self, button,valor):
        if valor  self.dado_atual:
            self.dado_atual = valor
            self.vezes = 1
            self.soma = 0
        else:
            self.vezes += 1
        self.montagem.set_text(string_jogada(self.vezes, self.dado_atual, self.soma))

    def incrementar(self, button,valor):
        self.soma = self.soma + valor
        self.montagem.set_text(string_jogada(self.vezes, self.dado_atual, self.soma))

    def show_message(self, message):
        dlg = hildon.Note('information', (self.window, message))
        dlg.run()
        dlg.destroy()
        #pango_markup = '%s\n%s' % ('DiceDnD', message)
        #hildon.hildon_banner_show_information_with_markup(gtk.Label(''), None, pango_markup)

    def quit(self, evt):
        gtk.main_quit()

    def run(self):
        gtk.main()

def main():
    prog = DiceDnD()
    prog.run()

if __name__ == "__main__":
    main()

Nokia N800

Adquiri recentemente o Nokia N800, um internet tablet. Meu intuito na sua compra é substituir o Palm (Tungsten E2) com vantagens, no caso internet wireless e sistema operacional Linux.
A grande tarefa inicial é encontrar programas tão úteis quanto os do Palm no quesito organização pessoal. Descobri que seu foco não é organização pessoal, mas sim Internet. A vantagem na busca de softwares em relação ao Palm é que procuramos e instalamos a la Debian, ou seja, nenhuma necessidade de sincronização com o Windows.
No segundo dia de uso, atualizei o seu firmware, como recomendado. Foi uma tarefa simples. Uma coisa que não gostei nele, foi a duração da bateria, entretanto, suspeito que seu suporte a redes sem fio contribua para isso. Nesse ponto, vou ter de me acostumar a desligar o aparelho.
Outra dificuldade que tenho é em relação a ambientes com proxy; somente o browser solicita o usuário e senha, conseguindo assim acesso à Internet.
No geral estou satisfeito com meu novo brinquedo. Antes que perguntem, o N800 não é um celular. Nesse caso, recomendo que comprei os novos celulares com Android.

TurboGears 2: solução de problemas durante a instalação

Pediram-me para documentar a instalação do TurboGears 2. Vocês podem encontrar os passos para a instalação aqui.

O restante deste post é sobre como solucionar certos problemas. Então, se você seguiu a documentação oficial e não teve problemas não precisa mais ler este post.

É bom salientar que fiz a instalação no Ubuntu Linux.

Installing TurboGears 2 from Source

Nesse ponto, quando vocês forem instalar o tg2 com python setup.py develop, vocês não encontrarão o arquivo setup.py. Ocorre que agora o tg2 usa o paver como instalador. Ou seja, documentação desatualizada. Na raiz de tg2 execute sudo paver develop.

Pode ser que durante o download das dependências do tgdev, não seja encontrado a versão 0.8.7dev do ToscaWidgets. Se este for o caso, é melhor você esperar um tempo para eles disponibilizarem-na e então sincronize a cópia de trabalho com svn update. Depois, execute novamente sudo python setup.py develop.

Concluídas as demandas, você já pode brincar com o TurboGears 2. Comece pelo Wiki em 20 minutos.

Estou querendo instalar o TG2 no Windows, então os problemas que possa encontrar vou colocar como comentário aqui.

O cárater Microsoft

Deve ser gostoso continuar sendo usuário do sistema operacional Windows mesmo sabendo dos meios sujos de como a Microsoft trabalha. Há muito deixei de lado o Windows e sou um usuário fiel do Linux. Tenho notebook e computador em casa. Rodam com Ubuntu Linux. No computador da casa dos meus pais, também roda Linux. Então, leia isso e veja se você pode ficar indignado. Eu fiquei.

Para meus amigos que desejam experimentar Linux, estou oferecendo suporte de seis meses gratuito. Só mesmo para aumentar o número de usuários Linux.

Não sou xiita, só acordei de mau-humor.

Install Fest 1.0 Piauí

install-fest-g1.pngDias 12 e 13 de março, no Auditório Afonso Sena e nos laboratórios do DIE e DCE na UFPI, acontecerá o primeiro Install Fest do Piauí.

Na programação consta o seguinte:

Dia 12:

  • Apresentação sobre Software Livre, GNU/Linux e Perfis de Usuário
  • Mesa Redonda

Dia 13:

  • Instalação do Install Fest, Cópias de imagens de distros Debian-like.
  • Encerramento com Evento Cultural no DCE/UFPI.

Variedade em distribuições Linux para Desktop

Acredito que o investimento feito nas distribuições focadas para o desktop foi o que aumentou o conhecimento do público para o Linux como um todo. Para o ambiente móvel, foi uma aposta das próprias empresas, uma vez que seria mais fácil bater a Microsoft (que ainda não investiu muito nessa área, ao contrário do Google).

Não se pode dizer que melhorar o desktop do Linux seria uma aposta boa o suficiente para bater o Windows. Mas, já bate o MacOS X, por exemplo. Apesar da incrível quantidade de distribuições, poucas podem ser consideradas de grande destaque no mercado atual para desktops: Suse, Ubuntu, Mandriva, Fedora e OpenSuse.

A Canonical chega ao Brasil e ela vai entrar no mercado pelo Programa Computador para Todos. O bom disso é que o Ubuntu é muito amigável e vai forçar as distribuições dos computadores atuais ficarem mais elegantes e menos infantis em seu design. Comprei recentemente um PC da Itautec e não gostei do Librix em termos de design. Faz você desejar mudar para o Windows. Ainda gostaria que o Ubuntu melhorasse suas cores.

Se não estou enganado, a Mandriva está nesse mercado também. Dentro do Brasil, o uso de Linux está ficando bastante sério, não só no meio corporativo mas no uso diário. Essa cultura de trocar o Linux pelo Windows vai mudar. Estou percebendo isso. As estatísticas ainda são esmagadoras contra o Linux apesar do meu positivismo. O que não me deixa menos otimista.

Liberdade de escolha

Alguns consideram que a variedade de distribuições atrapalham o mercado. Eu estou do lado da opinião que diz que variedade é uma coisa boa, porque podemos comparar e sempre melhorar. Se gosto de uma distribuição X e meu amigo gosta da Y, qual o problema? A verdade é que para o assunto que estamos tratando, Desktop, essa variedade torna a escolha uma coisa atraente e não o contrário. Impor algo para o cliente não é uma coisa boa.

Menos licenças, mais pessoas

Como engenheiro de software, torço para que as empresas e instituições governamentais gastem menos com licenças, e repassem isso para um setor estratégico (não só operacional como a maioria ainda pensa) que é a área de TI, tanto por meio de melhores salários quanto com treinamentos.

Powered by ScribeFire.