As rádios on-line não são nenhuma novidade, porém são recursos muito interessantes (sobretudo àqueles que sempre estão querendo conhecer novos estilos musicais e culturas diferentes). Para os padrões de conectividade atuais, é perfeitamente possível ouvir uma rádio on-line com uma conexão de Internet comum. Este post ensinará você a construir seu próprio player de rádio on-line no Linux!
Pré-requisitos
Para reproduzir o projeto proposto, os seguintes pré-requisitos são necessarios:
- Possuir algum dispositivo com acesso à Internet, saída de som e com alguma distribuição Linux instalada (ou até mesmo uma máquina virtual Linux). Este projeto foi testado com sucesso em distribuições derivadas da Debian.
- Conhecimentos básicos de Python
- Conhecimentos básicos de Linux
- Conhecimentos básicos de algum editor de texto em modo terminal do Linux (exemplo: VI e Nano)
Estratégia do projeto
Este projeto é, na verdade, um controlador de um player consagrado do Linux. O player em questão chama-se mplayer. Trata-se de um player muito leve e versátil para o Linux. Ou seja, o projeto se comunica com o player e este (rodando em “background”) obedece aos comandos desejados. Para isto ser possível, o mplayer opera em modo slave.
Os comandos são trafegados utilizando um recurso chamado named pipes. Isto permite que processos distintos no Linux se comuniquem / enviem mensagens uns aos outros, ficando a cargo do sistema operacional (neste caso, o kernel do Linux) gerenciar a transferências destas mensagens. No caso específico deste projeto, as mensagens trafegadas entre o receptor e o mplayer são os comandos que o mplayer aceita em modo slave, e são escritas e lidas em arquivos FIFO salvos no diretório /tmp.
[stextbox id=”info” caption=”Dica:” color=”000000″ bcolor=”FBFF77″ bgcolor=”FBFF77″ bgcolorto=”FBFF77″]Sempre que for fazer este tipo de comunicação entre processos, o arquivo FIFO é mapeado em RAM, independente de onde você criá-lo (ou seja, ele não pertence de verdade ao filesystem / não é um arquivo de fato). Essa característica é default do Linux, e oferece desta forma muito mais velocidade de escrita e leitura.
Além disso, em se tratando de Linux embarcado, isto é essencial para evitar múltiplas escritas em memória Flash (o que é “mortal” para este tipo de sistema, uma vez que pode levar à falha completa da Flash em pouco tempo devido ao limite de escritas que toda memória Flash possui).[/stextbox]
Para uma referência completa dos comandos do mplayer em modo slave, clique aqui.
Preparando o terreno
Antes de fazer o projeto propriamente dito, são necessárias algumas etapas prévias:
– Instalação do mplayer
Para instalar o mplayer, basta utilizar o comando abaixo:
sudo apt-get install mplayer2
– Escolha das rádios
Uma das formas do mplayer tocar uma rádio on-line é através do link de sua playlist (arquivo .pls). Portanto, ao escolher suas rádios a serem ouvidas, procure pela playlist em formato .pls. Abaixo há alguns exemplos:
- http://yp.shoutcast.com/sbin/tunein-station.pls?id=1057392
- http://panel3.serverhostingcenter.com:2199/tunein/radiobackstage1.pls
- http://yp.shoutcast.com/sbin/tunein-station.pls?id=1425714
Dica: um ótimo lugar para buscar rádios on-line é o Shoutcast.
Testando o mplayer junto com suas estações de rádio online
Antes de partir para o projeto em si, é prudente verificar se o mplayer toca corretamente sua rádio on-line. Este teste é necessário pois pode ser que a rádio esteja temporariamente fora do ar (melhor saber isso antes de quebrar a cabeça com um problema que não está “do seu lado”, concorda?).
A forma de fazer isso, considerando um exemplo de rádio on-line, pode ser vista abaixo:
mplayer -playlist http://panel3.serverhostingcenter.com:2199/tunein/radiobackstage1.pls
Feito isso, o mplayer inicializará e tocará a rádio on-line. Para sair do mplayer, basta pressionar a tecla ‘q’ (ou interromper a aplicação pressionado Ctrl + C).
Talk is cheap. Show me the code!
Chegou a hora do código! O projeto foi desenvolvido em Python. O código-fonte do projeto do receptor de rádio online pode ser visto abaixo.
Se preferir, acesse o código-fonte no meu GitHub clicando aqui.
import os import sys import subprocess import shlex #Variaveis globais CaminhoArquivoControle="/tmp/ControleRadio" ComandoMPlayer = "mplayer -input file=/tmp/ControleRadio -slave -playlist " #Variaveis das playlists Playlists=[] #Array que contem todas as playlists NumeroPlaylists = 0 #quantidade de playlists NomesRadios=[] #Nomes das radios / playlists PlaylistEscolhida=0 #Indice da playlist escolhida NomeRadio1="Radio ShoutCast" NomeRadio2="Radio Backstage (www.radiobackstage.com)" #Funcao: inicia lista de playlists #Parametros: nenhum #Retorno: nenhum def IniciaListaPlaylists(): global Playlists global NomesRadios global NumeroPlaylists #playlist 1 Playlists.append("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1057392") NomesRadios.append("Radio Shoutcast") #playlist 2 Playlists.append("http://panel3.serverhostingcenter.com:2199/tunein/radiobackstage1.pls") NomesRadios.append("Radio Backstage") #playlist 3 Playlists.append("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1425714") NomesRadios.append("Techno") NumeroPlaylists=3 return #Funcao: Toca a plsylist escolhida #Parametros: nenhum #Retorno: nenhum def TocaPlaylist(PEscolhida): global Playlists global ComandoMPlayer os.system("pkill -f mplayer") ComandoPlaylist = ComandoMPlayer + Playlists[PEscolhida] #inicia processo e direciona o stdout para /dev/null FNULL = open(os.devnull,'w') args = shlex.split(ComandoPlaylist) InterfaceMPlayer = subprocess.Popen(args, shell=False, stdin=subprocess.PIPE, stdout=FNULL, stderr=subprocess.STDOUT) #ajusta volume em 50% os.system('echo "volume 50" >'+CaminhoArquivoControle) return #Funcao: cria arquivo de controle do player (MPlayer) #Parametros: nenhum #Retorno: nenhum def CriaArquivoControle(): #se arquivo ja existe, nada e feito. if (os.path.exists(CaminhoArquivoControle)): return try: os.mkfifo(CaminhoArquivoControle) except: print "Falha ao criar arquivo de controle. Por favor, verifique o caminho de criacao do mesmo." exit(1) #Funcao: escreve na tela o menu de opcoes #Parametros: nenhum #Retorno: opcao escolhida def MostraMenuDeOpcoes(): global NomesRadios global PlaylitsEscolhida print "-----------------------" print " Menu de opcoes " print "-----------------------" print "Estacao: "+NomesRadios[PlaylistEscolhida] print " " print "<p> Play/pause" print "<s> Sair" print "<+> Sobe volume" print "<-> Desce volume" print "<d> Proxima estacao" print "<a> Estacao anterior" print " " opcao = raw_input("Opcao> ") return opcao #------------------ #Programa principal #------------------ #Inicializa lista de playlists IniciaListaPlaylists() #Cria arquivo de controle e inicia processo MPlayer CriaArquivoControle() #Toca playlist 1 TocaPlaylist(PlaylistEscolhida) while True: try: os.system("clear") Tecla = MostraMenuDeOpcoes() if (Tecla == "p"): print "[ACAO] Play/Pause" os.system('echo "pause" > '+CaminhoArquivoControle) if (Tecla == "s"): print "[ACAO] Sair" os.system('echo "quit 0" > '+CaminhoArquivoControle) os.system("pkill -f mplayer") exit(1) if (Tecla == "+"): print "[ACAO] Sobe volume" os.system('echo "volume +10" > '+CaminhoArquivoControle) if (Tecla == "-"): print "[ACAO] Desce volume" os.system('echo "volume -10" > '+CaminhoArquivoControle) if (Tecla == "d"): print "[ACAO] Proxima estacao" PlaylistEscolhida = PlaylistEscolhida + 1 if (PlaylistEscolhida == NumeroPlaylists): PlaylistEscolhida = 0 TocaPlaylist(PlaylistEscolhida) if (Tecla == "a"): print "[ACAO] Estacao anterior" PlaylistEscolhida = PlaylistEscolhida - 1 if (PlaylistEscolhida < 0): PlaylistEscolhida = NumeroPlaylists-1 TocaPlaylist(PlaylistEscolhida) except (KeyboardInterrupt): print "Aplicacao sendo encerrada." exit(1)
Para executar o projeto, basta salvar seu script com qualquer nome e executá-lo com o seguinte comando:
python NOMEDOSEUSCRIPT.py
Resultado
Veja abaixo as fotos e vídeo do resultado do projeto:
Fotos:
[slideshow_deploy id=’337′]
Vídeo:
Trabalhos futuros /próximos passos
Este projeto é algo experimental. O objetivo deste é, além de fazer com que você desenvolvedor crie algo divertido (afinal, quem não gosta de ouvir música, não é mesmo?), a familiarização com comunicação entre processos no Linux.
Se for seu desejo melhorar este projeto, segue abaixo alguns pontos aos quais sugiro melhorias:
- Substituição do pkill -f (comando que mata processos com nomes familiares ao qual lhe é passado como parâmetro) por um kill no PID do processo exato do mplayer. Isto garante que outros processos com nomes semelhantes a mplayer não sejam interrompidos por acidente.
- Substituição da escrita em FIFO através de os.system() por escritas não-blocantes diretamente no arquivo FIFO.
- Acrescentar uma interface gráfica
Agradecimentos
Segue aqui um agradecimento especial ao Cleiton Bueno e Felipe Lavratti por toda a ajuda e paciência em me ajudar neste projeto. Muito obrigado mesmo!
Gostou do artigo? Tem dúvidas? Tem críticas? Comente abaixo!