Robowebert Player, tocador de áudio em Java

Tenho desenvolvido nesses últimos meses (desde Fevereiro, para ser mais exato) um player de áudio escrito em Java no qual eu batizei de Robowebert Player. Ele reproduz áudio nos formatos MP3, OGG, Speex, FLAC e Monkey’s Audio, além dos formatos padrão do Java (AIFF, WAV e alguns outros). Suporta a leitura e salvamento de quatro formatos de playlists: M3U, PLS, XSPF e um formato próprio que estou desenvolvendo, chamado de RWPF. Além disso, possui um analisador de espectro, que é aquele monte de barrinhas que ficam subindo e descendo enquanto a música toca, além de controle de volume e de balanço, repetição de músicas, visualização dos metadados das músicas e uma barra de progresso meio capenga.

Tudo começou quando eu pesquisei pela Internet como fazer para tocar sons com Java. Encontrei um pequeno tutorial de como tocar arquivos MP3 usando a biblioteca JLayer, disponibilizada no site JavaZOOM.net e desenvolvi um minúsculo player que tocava apenas MP3 e que em sua interface possuía apenas três botões, um para selecionar a música, um para tocar a música e o último para parar de tocar a música. O player e mais a tela gráfica tinham cerca de umas cem linhas de código (ou nem isso). Com certeza, deve ser o menor player de MP3 da história.

Aí eu tive a ideia de desenvolver um player maior, que tocasse outros formatos de áudio além do MP3. Pensei em criar um subsistema para cada formato que o player fosse suportar. Entretanto, percebi o quanto isso iria ser difícil, pois a API da biblioteca JOrbis (biblioteca de suporte ao formato OGG) é completamente diferente da API do JLayer, além de mais complexa e de mais baixo nível.

Então, acessando o site do JavaZOOM acima citado, vi que os próprios desenvolvedores do JLayer desenvolveram um player em Java chamado JLGui, que suportava MP3, OGG e outros formatos de áudio. Era basicamente um clone do WinAmp e suportava os skins feitos para este. Resolvi testá-lo e não gostei muito de sua confusa interface, que além de confusa, a metade desta insistia em ficar na frente de todas as outras janelas. Para complicar, o player em si tinha uns bugs idiotas.

O JLGui é licenciado sob a LGPL, uma licença livre que me permite modificar o software de acordo com minhas necessidades. Entretanto, o código-fonte desse player é extremamente confuso, macarrônico e de extrema dificuldade de manutenção, além de ter sua camada de apresentação (o código responsável pela tela gráfica) colada na camada de negócios (o código responsável pela regra de negócios). Ou pior: todas as partes do player são coladas em várias outras partes.

Só para se ter uma ideia, se eu quisesse adicionar o suporte ao formato de playlist XSPF a este player, eu teria que fazer toda uma reengenharia no programa inteiro, praticamente.

A única parte que não era colada a nenhuma outra era o motor de execução de áudio, que foi concebido para ser aproveitado em outros softwares que desejassem tocar áudio com uma API de alto nível. Tal motor de execução era mantido em uma biblioteca separada chamada BasicPlayer.

O BasicPlayer utiliza uma API comum para todos os formatos de áudio baseada na API Java Sound, que usa Service Providers (bibliotecas especiais) que proveem o suporte aos formatos de áudio sem alterar o código-fonte que reproduz a música. Nas minhas pesquisas iniciais, eu já havia visto algo sobre a API Java Sound, entretanto, vi que ela era bastante confusa e de baixo nível. Já o BasicPlayer era de alto nível.

O que resolvi fazer? Criar um player que utilizasse o BasicPlayer como motor de execução de áudio. Aproveitei a interface simplória do minúsculo player que eu havia feito e a adaptei no BasicPlayer. A partir daí, fui implementando outras funcionalidades básicas, como controle de volume e de balanço e o botão de pausar e continuar a reprodução do áudio.

Aí o player foi evoluindo: passou a trabalhar com uma playlist na memória e a salvar e carregar um formato próprio de playlists baseado em XML, ganhou também botões de voltar à música anterior, voltar ao começo da música atual e ir para a próxima música.

Resolvi implementar o suporte à visualização dos metadados dos arquivos de áudio. O primeiro lugar onde pesquisei como fazer isso foi no macarrônico código do JLGui. Essa parte do código do JLGui não estava tão macarrônica e ligada às demais partes do player como as outras (só um pouco), então eu resolvi pegar este código e adaptá-lo ao meu próprio player, fazendo alterações diversas a fim de retirar completamente a dependência das outras partes do JLGui.

Já com o suporte aos metadados das músicas e mesmo com a interface estando muito tosca, disponibilizei o player (ainda sem nome naquela época) para alguns membros da comunidade Linux versus Windows do Orkut para ver o que eles achavam. Eles emitiram suas opiniões e o que eles gostariam de ver no player.

A partir daí, continuei a adicionar outros recursos ao player e a mudar um pouco sua interface (que ainda está tosca, mas menos do que antes). O último recurso adicionado até o momento foi o analizador de espectro, provido pela biblioteca KJ DSS.

O código-fonte do meu player, ao contrário do código do JLGui, é bastante claro e simples. O suporte à playlist na memória, por exemplo, é implementado por uma classe que gerencia um simples ArrayList contendo os objetos File, que provém acesso aos arquivos de áudio no HD. Já o JLGui implementa a mesma coisa com algumas classes, uma delas responsável por cada música na playlist (e que contém parte do código para manipular playlists no formato M3U – e manipular mal), outra cheia de métodos e mais uma interface gigantesca, além de mais algum código macarrônico colado na interface gráfica e em mais não sei onde.

Pelo fato da camada de apresentação ser completamente desacoplada da camada de negócios, será possível escrever telas gráficas alternativas ao visual atual do meu player. Inclusive, estou planejando para o futuro uma interface totalmente diferente e inovadora além da que já existe, além de uma interface alternativa usando a SwingWT, implementação alternativa (e mais leve) da API Swing baseada na biblioteca SWT.

No link abaixo, uma screenshot de como está o visual do meu player atualmente:

http://img30.imageshack.us/img30/4513/rwplayer.png

Ainda falta a grande maioria dos recursos que desejo implementar no meu player, como biblioteca de mídia, playlists dinâmicas, execução aleatória de músicas contidas numa playlist, edição de metadados das músicas, internacionalização e uma penca de outras coisas. O player vai ficar o bicho.

Entretanto, irei disponibilizar uma segunda versão pública com apenas alguns desses recursos, quando eu achar que ele está bom o suficiente para ser usado pelo público geral, ainda que incompleto. Irei disponibilizá-lo no SourceForge.net, onde já mantenho hospedado outro software que desenvolvo, o CapeTrivia.

Meu Player será licenciado sob a GPL 3, ou melhor, o código que escrevi está sob esta licença. O subsistema de leitura de metadados está sob a LGPL 2.0 pois não posso alterar a licença dessa parte, já que não fui eu que escrevi. E as demais bibliotecas estão nas suas respectivas licenças, todas compatíveis com a GPL 3.

Por falar em licenças, eu acabei tendo umas dúvidas com relação à compatibilidade destas, ainda mais por causa da biblioteca que provê o suporte ao formato de playlist XSPF (JSpiff) estar na licença Apache 2.0 e haver código LGPL 2.0 no player. Resolvi mandar um e-mail para o Richard Stallman, presidente da Free Software Foundation (ou melhor, dois e-mails, o outro foi depois da resposta que ele me mandou). A troca de e-mails com o Stallman merece um post à parte (no próximo deste blog, quem sabe), mas resumidamente, ele respondeu que as licenças são todas compatíveis entre si.

Escolhi o nome Robowebert Player a fim de homenagear um antigo personagem das minhas histórias infantis de quando eu era criança e que eu mesmo inventei, o Robowebert. Este era um robô gigantesco ao estilo do Megazord dos Power Rangers que possuía vários componentes integrados e recursos diversos e que tinha a finalidade de lutar contra inimigos gigantescos que ameaçavam a cidade de Pret-a. O Robowebert era controlado pela Darker Webert, uma mulher que combatia o crime naquela cidade fictícia e que vivia cheia da grana. Ela também merece um post à parte, pois teve uma importância histórica na minha infância.

Não há uma previsão de quando a próxima versão pública (e desta vez disponível ao público geral e não só a alguns membros da Linux versus Windows) será disponibilizada, mas espero ver o Robowebert Player na próxima versão estável do Debian, codinome Squeeze, a ser lançada provavelmente no ano que vem.

Atualização: escrevi um novo post sobre o Robowebert Player, que pode ser visto em: https://irmaodamara.wordpress.com/2010/07/12/mais-sobre-o-robowebert-player/

Anúncios

16 Respostas to “Robowebert Player, tocador de áudio em Java”

  1. Ricardo Says:

    Fala Alan, beleza?

    Vi que você está fazendo um player. E estou querendo fazer um programinha em java também, mas nem comecei ainda… Estou pesquisando como irei fazer. Minha idéia é fazer um software que irá comparar a onda do áudio e verificar sem tem outros áudios iguais no computador. Minha primeira dificildade é trabalhar com mp3.

    Qualquer dica que você puder dar…Será bem vinda…

    Abraços

  2. Apesar de eu estar desenvolvendo um player de áudio, eu não estou muito familiarizado com a API de som do Java (Java Sound API), sei algumas coisas básicas. Inclusive, o motor de reprodução de áudio do meu player é uma versão modificada do motor do JLGui.

    De qualquer forma, recomendo que estude a API de som do Java. Para trabalhar com MP3, existe o JLayer, uma biblioteca que implementa o suporte a MP3 no Java. Não sei se com ela dê para fazer o que você quer, mas é bom dar uma olhada.

  3. O ALAN QUER COMPETIR DE IGUAL PARA IGUAL COM O MEDIA PLAYER!
    ^^

  4. Para competir com o Windows Mmedia Player, meu player teria que reproduzir vídeos também. no caso, me player compete com o XMMS, um lendário player de áudio para Linux que é um clone do famoso Winamp.

  5. Boa tarde Alan!

    Este seu primeiro pequeno player você fez em Java Sound?
    Poderia me encaminhar o source dele?

  6. Leandro Garcia Says:

    Tem como voce emviar o codigo dele?

  7. Assim como enviei para o Leandro (acima), estou lhe enviando agora o código mais atual do Robowebert Player.

  8. U. Master Says:

    Olá amigo,

    Vi a foto do seu player e está absurdamente bem feito… Estou pensando em criar um player também, apenas por teste.

    Poderia me enviar seu source code para que eu possa estudá-lo?
    Parabéns!

  9. Tem como me enviar o código fonte do primeiro player(aquele que a parte gráfica tem apenas no máximo 3 linhas)?

    Se poder mande o link para mcirqueira11@gmail.com.

    Obrigado!!!
    Mande também o jar(estudo java e nunca aprendi a compactar em jar).
    Tchau!!! e agardo resposta.

  10. No sábado, eu lhe enviarei o código-fonte e o jar, neste momento, eu não tenho como lhe enviar. Ou melhor, acho que eu colarei o código-fonte num pastebin, assim este ficará disponível para quem quiser ver o código.

  11. OI Alan, li o seu post, e como vi que a data já está antiga de hoje 24/08/12 imagino que vc já está super milionário com o player que inventou, parabéns cara !!!
    Porém, se vc ainda estiver vivo, queria uma ajuda em como tocar uma gravação em um player que seria startado por um sensor binário por exemplo. estou fazendo um trabalho pra faculdade e pretendo fazer um estacionamento, então..na chegada do veículo o sensor aciona o player que emite a mensagem de boas vindas.
    AH e como percebi em seus comentários que vc é um cara que não se importa de ensinar e ajudar os mais necessitados eu gostaria de ter o código de seu player tbém, se possível até aquele mais simplezinho. agradeço, boa sorte e Sucesso !!!!

  12. Eu ainda estou vivo, mas não fiquei milionário, uma vez que o Robowebert Player não possui fins comerciais, além de eu não ter ganho na Mega-Sena.

    Eu não faço ideia de como integrar um sensor que detecta a chegada de um veículo a uma aplicação Java, e nem sei se isto é possível (talvez com JNI seja possível). E acredito que esse tipo de aplicação seja melhor feito com linguagem C, C++ ou Pascal, ou outra do tipo.

    No post abaixo, há links para o código do player mais simples, composto de apenas dois arquivos fonte:

    https://irmaodamara.wordpress.com/2011/09/19/apanhado-de-assuntos-sortidos/

    Já o Robowebert Player, irei lhe enviar no seu e-mail o código-fonte do mesmo ainda nesse fim de semana. Ultimamente eu não tenho tido muito tempo para prosseguir no projeto, mas espero retomar o mesmo no fim deste ano ou no ano que vem. Mas ele já está com alguns recursos legais implementados, inclusive com suporte a internacionalização, com parte de sua interface já traduzida para o inglês. Quando o player possuir alguns recursos nos quais eu acho nesessário, o mesmo será disponibilizado no Sourceforge.

  13. Marcos Says:

    Alan, vi seu projeto que é bem interessante ate mesmo pelo fato de ser GPL.
    Na faculdade, temos um projeto que consiste em adicionar uma extensao a um player, permitindo que ele interaja com um arduino, de maneira que por meio do arduinoi seja possivel detectar a intensidade sonora e feito isto, o volume do player aumenta ou diminui.
    Porem, nao encontramos um player que seja mais simples para que possamos fazer isso.
    Voce poderia nos passar o codigo fonte do seu trabalho, para que a gente possa tentar evoluir na implementacao?

    Obrigado
    Abracos
    MArcos

  14. Já faz tempo mas , para integrar aplicativos com interfaces do mundo real use microcontroladores Arduino ou PIC da Microchip é uma opção daí você codifica o que quiser que ele faça.

  15. Acho que isso não teria muito a ver com a proposta do meu projeto.

  16. Antonio Says:

    Estou com a mesma ideia do Ricardo lá em cima. Quero construir algum programa que possa comparar dois arquivos (principalmente áudio, mas não necessariamente) e dizer se são iguais. Mas penso em fazer sem necessariamente usar banco de dados (de início pelo menos). Seria, vamos dizer assim, no “mano a mano”. Se é que é possível.
    Andei pesquisando e pelo o que entendi para analisar o espectro (onda) do áudio é preciso usar muitas ferramentas avançadas como, por exemplo, transformada de Fourier.
    Achei muito interessante seu trabalho e fiquei interessado em ver como fez com o metadados e com o analisador de espectro. Seria possível você me enviar seu código? Não pretendo copiar, pretendo entender pois estou querendo fazer algo não necessariamente em java. Quero mesmo é entender como se manipula áudio com um pouco de programação.
    Outra coisa, seria possível fazer tudo ou parte do que você fez com programação direta sem usar bibliotecas, ou seja, construir o código todo sem usar adendos? É que sou iniciante e imagino sem ter muita certeza que bibliotecas, do jeito que estão definidas, são mutáveis de acordo com necessidades alheias a nossa própria vontade.

    Desde já te agradeço, parabenizo e peço desculpa pelo incomodo.

Comente este post!

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s