Quase todos os dias ouço música no meu smartphone e uso os botões de controle no fone de ouvido. Mas eu sempre não gostei de uma coisa. Volto para casa, continuando a ouvir, o fone de ouvido se conecta ao meu PC em casa - e de repente os botões param de funcionar.
Obviamente, pesquisei a solução para este problema. Infelizmente, no Windows, esse recurso maravilhoso não é muito suportado. Alguns minutos de pesquisa deram apenas menções turvas no Stack Overflow sobre placas de som e mensagens de algumas pessoas de que tudo funcionava bem em seus laptops.
Isso não me assustou - e decidi aceitar o problema como um desafio interessante: é possível criar algum tipo de programa para ativar os botões de controle, se não houver suporte de hardware para eles? A resposta é sim, você pode. E eis como fazê-lo em meia hora.
Como funcionam os botões do fone de ouvido Android
A primeira coisa a entender é como os botões do fone de ouvido funcionam. Uma pesquisa rápida na Internet encontrou
essa especificação na documentação do Android. Há um gráfico lá.

Como você pode entender, quando você pressiona um botão no fone de ouvido, o circuito em um dos resistores se fecha. Destaca-se o botão A (Reproduzir / Pausar / Gancho) com uma resistência de 0 ohms, ou seja, um curto-circuito do microfone. Se conseguirmos detectar um curto-circuito no microfone, podemos determinar a pressão do botão Reproduzir / Pausar.
Teste de hipótese
Antes de iniciar a programação, gostaria de verificar a razoabilidade do nosso raciocínio em princípio. Ou seja, o fato de que o sinal do microfone pode ser determinado pressionando o botão Reproduzir / Pausar. Felizmente, para isso, basta gravar o som no computador e observar o resultado. Lancei o Audacity, pressionei o botão Reproduzir / Pausar durante a gravação - e recebi esse sinal.
BingoComo você pode ver, pressionar o botão é obviamente refletido na forma de onda: uma queda repentina para -1 seguida de uma transição repentina para 1 e uma diminuição gradual para 0. Intuitivamente pela especificação, eu assumiria que o sinal salta para 1 e permanece lá até o botão ser liberado, mas na realidade, parece diferente. No entanto, essa imagem ainda é fácil de detectar se você capturar o fluxo de áudio do microfone.
Captura de som com Python
Conhecendo a maneira de detectar o pressionamento de botão no fone de ouvido, você pode pensar no objetivo principal: como controlar o player na área de trabalho usando os botões do fone de ouvido.
O primeiro passo é detectar um clique no botão. Para fazer isso, você precisa pegar o fluxo de áudio do microfone e descobrir a assinatura distinta que vimos anteriormente. Para simplificar, implementamos a solução em Python. Após outra pequena pesquisa na Internet, encontrei um pacote chamado sounddevice, que permite abstrair da parte mais difícil - captura de áudio real de um microfone.
Um pouco de codificação nos dá o seguinte:
import sounddevice as sd SAMPLE_RATE = 1000
Esse código produz continuamente o valor médio de cada lote de amostras. Definimos a taxa de amostragem para 1000, o que é terrivelmente pequeno para o processamento de som (geralmente é usado 44100), mas na verdade não precisamos de muita precisão. O tamanho do bloco determina quantas amostras no buffer acionam um retorno de chamada. Novamente, definimos valores muito baixos. Um tamanho de bloco de 100 e uma taxa de amostragem de 1000 na verdade significa acionar 10 vezes por segundo, onde apenas 100 amostras são processadas com cada chamada.
Detecção de clique no botão: provavelmente muito fácil
Agora capturamos o fluxo de áudio e podemos implementar um mecanismo real para detectar o pressionamento de botão. Lembre-se de que o sinal salta para 1 cada vez que você pressiona. Isso sugere a maneira mais fácil de detectar: se
N blocos consecutivos tiverem um valor de sinal acima de 0,9, ou seja, um clique.
Implementamos o algoritmo em nossa função:
import sounddevice as sd SAMPLE_RATE = 1000
De fato, lançamos um contador interno, quantos blocos processados atendem ao requisito de limite, que é simplesmente definido como 0,9, proporcionando o inevitável ruído da amostra. Se o bloco não atender ao requisito, o contador será redefinido - e começaremos novamente. A variável
is_held
monitora os acionadores para não registrá-los repetidamente se o botão não for liberado.
Controle de reprodução do Windows
Agora resta apenas substituir o comentário
"O botão foi pressionado!" No código real para controlar a reprodução de áudio no Windows. Google novamente para descobrir como fazer isso: você pode controlar a reprodução simulando pressionamentos de teclas com os
códigos de teclas virtuais correspondentes.
Aconteceu que simular pressionamentos de tecla é muito fácil com o pacote
pywin32 , que é apenas um shell Python para a API do Windows. Juntando tudo, podemos criar a seguinte função:
import win32api import win32con VK_MEDIA_PLAY_PAUSE = 0xB3 def toggle_play(): win32api.keybd_event(VK_MEDIA_PLAY_PAUSE, 0, 0, 0)
E nós conseguimos!
toggle_play
função
toggle_play
no lugar do código em que o comentário
"O botão foi pressionado!" , permite controlar qualquer media player no Windows usando os botões do fone de ouvido Android.
Testes mostraram que o código funciona surpreendentemente bem. A única diferença entre a funcionalidade no Android e no Windows é um pequeno atraso ao pressionar o botão, mas você pode conviver com ele.
E então o que aconteceuO script Python consiste em 51 linhas que ativam os botões no fone de ouvido Android no Windows. O código fonte final deste projeto está
no Github .
Espere, isso não é tudo!
Depois de usar o programa alegremente por várias horas, notei um problema sério:

O programa usa quase 30% da CPU! Obviamente, isso é inaceitável durante um longo trabalho, algo precisa ser feito. Observando o código, percebi que o thread principal está no estado ocioso no loop principal, embora nada aconteça lá. A solução mais lógica é simplesmente sacrificar o encadeamento para sempre: como o retorno de chamada é chamado automaticamente, ainda não precisamos de um loop.
from time import sleep if __name__ == '__main__': controller = HeadsetButtonController() while True: sleep(10)

Eu também não queria executar o script Python manualmente após cada inicialização do computador. Felizmente, o Python para Windows vem com um utilitário útil chamado pythonw.exe que inicia o processo daemon sem um terminal conectado. Colocamos um atalho para esse processo no diretório
Microsoft \ Windows \ Menu \ Programas \ Startup , especificando nosso script como o primeiro argumento - então o aplicativo é iniciado automaticamente e é executado silenciosamente em segundo plano.