Introdução
Um player de áudio bonito para a linha de comando do Linux.

Um player de áudio para quem tem hardware limitado e preza pelo bom uso dos recursos computacionais.
- Codificado inteiramente e C, para o maior desempenho.
- Player CLI(Command Line Interface), ou seja ele roda na terminal do Linux.
- Robusto e eficiênte, para rodar até nos micros mais antigos
A tarefa de decodificar arquivos MP3 e OGG é uma tarefa onerosa na questão de consumo de processamento, principalmente em hardwares antigos. O CMus tem uma interface visualmente agradável e bem intuitiva após o esclarecimento do seu conceito. Contudo, o processo de aprendizagem do uso do player CMus pode ser um pouco complicado para alguns usuários.
Site CMusFuncionamento

Produtor e Consumidor
O problema Produtor e Consumidor consiste em um conjunto de processos que compartilham um mesmo buffer. Os processos chamados produtores põem informação no buffer. Os processos chamados consumidores retiram informação deste buffer. O CMus faz uso dessa lógica para fazer o armazenamento dos arquivos de áudio a serem tocados como pode ser visto no arquivo player.c, logo no início já é feita a implementação das threads que serão responsáveis por executar os processos de alimentar e utilizar as informações no buffer. Esse buffer possui um tamanho fixo, definido por CHUNK_SIZE
no arquivo buffer.c, para ter informação suficiente para tocar a música sem cortes e também ser ágil na coleta desses dados.

Mutex
Também chamado de exclusão mútua, é uma técnica usada em programação concorrente para evitar que dois processos ou threads tenham acesso simultaneamente a um recurso compartilhado.
Para a implementação é a utilizado um semáforo binário, isto é, que só pode assumir dois valores distintos, 0 e 1. O travamento por semáforo deve ser feito antes da utilização do recurso, e após o seu uso o recurso deve ser liberado. Enquanto o recurso estiver em uso, qualquer outro processo que o utilize deve esperar a liberação.
Esse gerenciamento de recursos é utilizado no problema do Produtor e Consumidor, para que enquanto o dispositivo que está alimentando o buffer com os arquivos o aplicativo que está tocando esses arquivos não faça uso dos mesmos, junto da implementação das threads de produtor e consumidor no arquivo player.c é feita a implementação dos seus respectivos mutexes producer_mutex
e consumer_mutex
.

Pool de Threads
Um pool de threads é uma grupo de threads disponíveis para a realização de tarefas. O uso desse recurso é feito para otimizar o uso de threads em um programa, pois um programa com milhares de threads pode sofrer em desempenho. Por isso Pools geralmente provêem uma melhora na performance quando se executam um grande número de tarefas curtas e repetitivas.
Quando se usa um pool de threads não existe a preocupação com o ciclo de vida das threads, criação e destruição, pois é utilizado o princípio de manter um número de threads aguardando para que tarefas sejam atribuídas as elas.
Esse recurso se torna muito útil, já que o CMus utiliza um grande número de threads para fazer o controle e utilização das suas tarefas, como alimentação de buffer, consumo de buffer, implementação de mutex e jobs. Se essa implementação fosse feita sem um Pool de Threads o processamento poderia ficar lento dependendo da proporção de uso. A implementação da Pool de Threads no CMus é feita pelo arquivo worker.c, ele gerencia a execução das tarefas em uma lista.
A comunicação entre os processos é feita através de Synchronous messages, como a função cmus_get_next_track
que pode ser encontrada no arquivo cmus.c, quando é acionada ela procura a próxima música na lista de reprodução usando a thread principal do programa, chamada de main_thread
. Também encontramos comunicação por Asynchronous messages, que são os retornos dos jobs utilizados para implementar o Pool de Threads.
Lista de Threads
Para ilustrar a quantidade de threads utilizadas no programa, foi elaborada a tabela abaixo:
Thread | Local | Linha |
---|---|---|
cond |
locking.c | 28 |
main_thread |
locking.c | 31 |
worker_mutex |
worker.c | 46 |
worker_cond |
worker.c | 47 |
worker_thread |
worker.c | 48 |
cmus_next_file_mutex |
cmus.c | 59 |
cmus_next_file_cond |
cmus.c | 60 |
mutex |
cmus.c | 407 |
this_thread |
cmus.c | 428 |
buffer_mutex |
buffer.c | 48 |
job_mutex |
job.c | 89 |
ip_lock |
input.c | 100 |
player_info_mutex |
player.c | 60 |
producer_thread |
player.c | 95 |
producer_mutex |
player.c | 96 |
producer_playing |
player.c | 97 |
consumer_thread |
player.c | 102 |
consumer_mutex |
player.c | 103 |
consumer_playing |
player.c | 104 |
attr |
player.c | 1018 |
Código Aberto
Código totalmente aberto que pode ser baixado!