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!


Pedro Bertoleti

Informações completas em: http://pedrobertoleti.com.br/index.php/sobre/