Wyciszenie głośników, gdy zostaną podłączone słuchawki

Uwaga: Ten wpis został utworzony ponad rok temu. Informacje w nim zawarte mogą być nieaktualne!

Jako posiadacz laptopa miałem z ciągły problem z jednoczesnym dźwiękiem z wbudowanych głośników i podpiętych słuchawek. Próbowałem wielu sposobów, kombinowałem z Alsą, z Pulseaudio… nic. Do czasu! Do czasu natknięcia się na skrypt, który automatycznie wyciszy wbudowane głośniki, gdy zostaną podpięte słuchawki/głośniki w gniazdo.

Autorem skryptu jest xtr.

Otwórz edytor tekstu i wklej do niego kod:

/*
* File:   main.cpp
* Author: xtr
*
* Created on April 26, 2010, 5:26 PM
*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <syslog.h>
#include <signal.h>
#include <sys/stat.h>

#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

#define HDA_VERB(nid,verb,param)    ((nid)<<24 | (verb)<<8 | (param))
#define HDA_IOCTL_VERB_WRITE        _IOWR('H', 0x11, struct hda_verb_ioctl)

struct hda_verb_ioctl {
u32 verb;    /* HDA_VERB() */
u32 res;    /* response */
};

void daemonize()
{
pid_t pid, sid;

/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}

 /* Change the file mode mask */
umask(0);

/* Open any logs here */
openlog("pinsensed", LOG_PID, LOG_DAEMON);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}

 /* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}

/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);

}

bool done = false;

void trpsig(int)
{
done = true;
}

int main(int argc, char** argv) {
daemonize();
signal(SIGTERM, &trpsig);

 int fd, state;
struct hda_verb_ioctl val;
syslog(LOG_INFO, "Daemon started.");
fd = open("/dev/snd/hwC0D0", O_RDWR);
if (fd < 0) {
syslog(LOG_ERR, "Failed to open snd device.");
exit(EXIT_FAILURE);
}
val.verb = HDA_VERB(0x19, 0x0f09, 0x0);
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0)
syslog(LOG_ERR, "Failed to write hda verb.");
state = val.res >> 31;
syslog(LOG_INFO, "Starting input value: %0x", state);
while(!done)
{
sleep(1);
val.verb = HDA_VERB(0x19, 0x0f09, 0x0);
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0)
syslog(LOG_ERR, "Failed to write hda verb.");

 if(state != (val.res >> 31))
{
state = (val.res >> 31);
syslog(LOG_INFO, "New input value: %0x", state);
if(state == 0x1)
val.verb = HDA_VERB(0x1f, 0x701, 0x1);
else
val.verb = HDA_VERB(0x1f, 0x701, 0x0);
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0)
syslog(LOG_ERR, "Failed to write hda verb.");
}
}
close(fd);
syslog(LOG_INFO, "Daemon stopped.");
exit(EXIT_SUCCESS);
}

Zapisz plik jako pinsensed.cpp. Przejdź do katalogu, w którym zapisałeś ten plik i go skompiluj:

g++ pinsensed.cpp -o pinsensed

Skopiuj plik do katalogu /usr/local/bin/:

sudo cp pinsensed /usr/local/bin/pinsensed

Uruchom skrypt:

sudo pinsensed

Sprawdź czy działa – nie ma innego wyjścia :) Teraz dodaj skrypt do autostartu:

sudo gedit /etc/init.d/rc.local

I pod ostatnią linijką komentarza w nagłówku, czyli:

### END INIT INFO

Dodaj:

/usr/local/bin/pinsensed

Zapisz plik i uruchom ponownie komputer, aby sprawdzić czy skrypt startuje prawidłowo.

Jeżeli powyższy artykuł nie rozwiązał lub rozwiązał częściowo Twój problem, dodaj swój komentarz opisujący, w którym miejscu napotkałeś trudności.
Mile widziane komentarze z uwagami lub informacjami o rozwiązaniu problemu.
  • http://launchpad.net/~chmiela-st Aragwain

    Hmm, zwykle jest to automatycznie robione. W sensie, że problem w ogóle się nie pojawia. Ale widać to kwestia karty dźwiękowej. ;)

  • http://www.qkiz.pl QkiZ

    Potwierdzam. Też nie mam z tym problemu.

  • Ania

    Widocznie macie porządne laptopy :)

  • colld

    mój laptop nie jest porządny, hp compaq nx6110. skrypt nie działa. w wersji ubuntu 8.04 udało mi się to załatwić poprzez regulację głośności – zakładka przełączniki – zaznaczenie headphone jack sense
    a teraz?

  • http://www.ubuntu-pomoc.org Szmitas

    Zwróć uwagę na początek kodu, są tam gwiazdki, które należy usunąć, zrobiłeś to?

  • Rodziu

    Takie moje małe spostrzeżenia:
    – skrypt nie zaskoczył, w przypadku gdy po wykonaniu wszystkich instrukcji, w czasie resetu głośniki były podłączone (zadziałał dopiero reset z odłączonymi głośnikami).
    – przy pierwszej regulacji głośności (za pomocą skrótu klawiszowego), ponownie załączyły się głośniki wbudowane, jednak po wyciągnięciu i ponownym włożeniu wtyczki od głośników wszystko znów działało jak należy.
    Teraz wszystko śmiga :)

  • Sawik

    Niestety u mnie nie zaskoczył wcale. Skrypt skompilował się, skopiował do katalogu, natomiast po odpaleniu go ręcznie poleceniem nie ma żadnego efektu (nie wyświetla się też błąd). Nie widzę też procesu o nazwie „pinsensed” w Monitorze Systemu. Pracuję na HP Pavilion dv6.

  • styk444

    Mi też nie działa ten skrypt na Amilo Pro

  • http://www.ofcasite.tk ofca

    nie działa. Acer Aspire One 722

  • obiwan

    Znalazłem o wiele prostszy i skuteczny (przynajmniej u mnie) sposób!
    Mianowicie:

    1) Otworzyć terminal
    2) WPISAĆ alsamixer
    3) Przesuwając strzłkami zaznaczyć Headphon
    4) Nacisnąć klawisz m żeby uaktywnić wyciszanie głośników

  • pablo

    Zrobiłem wszystko jak w opisie i niestety nic to nie dało, aczkolwiek na podstawie innych rozwiazan znalazłem sposób, wystarczy podłączyć słuchawki, badz jak w moim przypadku wieżę, odpalic terminal, wpisać alsamixer w moim przypadku mam ustawione Master F 00 a Front na MM i działa, oczywiście Front trzeba zgłośnić.

  • Sawik

    No tak, ale cały pic o to, żeby to działo się automatycznie… Bo nie uśmiecha mi się za każdym razem otwierać terminala, tylko po to żeby głośniki wyciszać. Ten i kilka innych problemów spowodował u mnie powrót do Windowsa, przynajmniej do czasu następnej reinstalacji systemu.

  • pablo

    skrypt też mam dodany do autostartu, aczkolwiek nie wiem, czy to coś daje, u mnie trzeba ręcznie przełączyć, ale myślę, że duży problem to nie jest, słuchawek raczej nie podłącza się na 2 minuty.

  • boczuleq

    Witam, chciałbym powiedzieć że jestem bardzo zadowolony i wdzięczny, za ten program. Jednak mam pewien problem ponieważ, wpisuję odpowiednią komendę by dodać do autostartu ten skrypt, jednak otrzymuję coś takiego:
    ” sudo: gedit/etc/init.d/rc.local: command not found ”
    Powiem jeszcze tylko, że dźwięk teraz działa.
    Dodam, że mam Xubuntu, a nie Ubuntu (może dlatego nie wykrywa mi tej komendy?)
    Pozdrawiam.
    Miłego dnia
    (:

    • http://www.ubuntu-pomoc.org Łukasz Schmidtke

      Między gedit a /etc jest spacja.

  • http://tmg.szczecin.pl tommy

    W czeluściach internetu, po dłuższym borykaniu się z tym problemem, znalazłem rozwiązanie, które u mnie zadziałało (skrypt nic nie dał). Posiadam HP nx6110.
    Otóż w pliku /etc/modprobe.d/alsa-base.conf dodałem na końcu linijkę: options snd-hda-intel model=laptop

    Restart i działa.

  • endriuh28

    Ja bym chciał efekt odwrotny, mam problem z gniazdem audio, uszkodziło mi się i teraz mam tak że Ubuntu myśli że mam coś podpięte pod gniazdo S/PDIF i nie odtwarza dźwięku mimo że nic nie mam podłączonego pod żadne gniazdo OUT.
    Mógłby mi ktoś napisać jak przerobić ten kod aby uzyskać efekt odwrotny, czyli wyłączyć auto wykrywanie?