Jak wstrzymać odtwarzanie VLC, gdy słuchawki są odłączone?

12

Jak można wstrzymać odtwarzanie VLC, gdy słuchawki są podłączone? Mogę wyciszyć głośniki za pomocą ALSA, ale chcę użyć spustu wtyczki, aby zatrzymać odtwarzanie, jak to zwykle jest w smartfonach.

HerHde
źródło
1
Uwaga: druga odpowiedź jest znacznie bardziej wydajna w momencie pisania: askubuntu.com/a/642898/20275
int_ua

Odpowiedzi:

5

Ok, więc bazując na tym, czego się tutaj nauczyłem , próbuję nowego podejścia, używając ACPI.

  1. Utwórz skrypt do wstrzymywania i cofania VLC:

    sudo touch /etc/acpi/headphone_jack.sh
    sudo chmod +x /etc/acpi/headphone_jack.sh
    

    i umieść w tym pliku:

    _pid=`pgrep vlc`
    _pid="${_pid% *}"
    DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$_pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'`
    _username=`grep -z USER= /proc/$_pid/environ |sed 's/.*=//'`
    
    if [ "$3" = unplug ]; then
        su $_username -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Pause"
    else
        su $_username -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Play"
    fi
    
  2. Teraz utwórzmy wyzwalacz zdarzeń (zamień na vimswój ulubiony edytor tekstu):

    sudo vim /etc/acpi/events/headphones
    

    i dodaj następujące:

    event=jack/headphone
    action=/etc/acpi/headphone_jack.sh %e
    
  3. Na koniec zrestartuj demona ACPI:

    sudo service acpid restart
    

Myślę, że powinno być dokładnie to, czego potrzebujesz, bez udziału sondowania. Jedyną wadą, jaką mogę znaleźć w tej implementacji, jest to, że wielu użytkowników korzysta z VLC w tym samym czasie. Przypuszczam, że w takim przypadku to podejście może losowo wstrzymać i wznowić jedno z nich (lub może po prostu nie działać).

Wielkie podziękowania dla @int_ua i @Sneetsher za przekazanie mi ważnej wiedzy na temat obsługi zdarzeń ACPI. Również kciuki do @ user3073656 za uproszczenie procedury.

Akrobacje
źródło
1
aby uruchomić dowolną komendę, która wymaga DBUS, musisz wyeksportować zmienną środowiskową działającej sesji dbus. Zobacz komentarz Germara do odpowiedzi Sneetshera.
daltonfury42
1
Dobrze zauważony. Oto najczystszy sposób, w jaki mogę to zrobić. Nie potrzeba skryptów autostartu i tak dalej.
Stunts
@Stunts, to najlepsze podejście, jakie widziałem, aby uzyskać docelową ENV. Możliwe jest uzyskanie użytkownika w ten sam sposób, grep -z USER /proc/$_pid/environaby działał dla wszystkich użytkowników na maszynie (z pojedynczą uruchomioną sesją / vlc). Szukałem takiej opcji.
user.dz
@Sneetsher: Sweet! Wygląda teraz znacznie lepiej. Ostatniej nocy przyszło mi do głowy, ale ostatniej nocy byłem zbyt zmęczony, żeby o tym myśleć. Dzięki za pchnięcie w tym kierunku.
Stunts
1
Nadal możesz poprawić odpowiedź, używając% e i używając tylko jednego pliku skryptu. Zobacz to .
daltonfury42
9

Ok, więc musisz zrobić kilka rzeczy:

  1. Wykryj, kiedy słuchawki są odłączone;
  2. Po zdarzeniu w (1) wyślij polecenie „pauza” do VLC;
  3. Wykryj, kiedy słuchawki zostaną ponownie podłączone;
  4. Po zdarzeniu w (3) wyślij polecenie „play” do VLC;

Dla (1) i (3): Możesz użyć tego, co pokazano tutaj . Ta odpowiedź zawiera małą procedurę, aby znaleźć różnicę między podłączonym i odłączonym gniazdem, oraz skrypt, który można zmodyfikować w celu dopasowania do przypadku.

Dla (2) i (4): Powinieneś użyć interfejsu Dbus VLC. Odpowiedni kod powinien być następujący:

dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Pause

dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Play

Odpowiednio do pauzy i odtwarzania.

Teraz o skrypcie. W twoim przypadku powinno to wyglądać mniej więcej tak:

#!/bin/bash
# This scripts detecs unplugging headphones.

oldstatus="unrelated string"
while [ 1 ]; do
    # The following line has to be changed depending on the difference (use diff) in '/proc/asound/card0/code#0'
    status=$(grep -A 4 'Node 0x16' '/proc/asound/card0/codec#0' |  grep 'Amp-Out vals:  \[0x80 0x80\]')
    if [ "$status" != "$oldstatus" ]; then
        if [ -n "$status" ]; then
            echo "Plugged in"
             dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Play
            oldstatus="$status"
        else
            echo "Unplugged"
            dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Pause
            oldstatus="$status"
        fi
    fi
    # Now sleep for 250 milli-seconds as per @Serg's request (who learnt if from @Fabby)
    # sleep is timer-based so doesn't use *any* processor cycles while sleeping.
    sleep 0.25
done

Dodaj ten zmodyfikowany skrypt do aplikacji startowych i gotowe. Myślę, że powinien zrobić to, co chciałeś.

PS - Zauważ, że istnieją bardziej wydajne sposoby, aby to zrobić, takie jak inotifywykrywanie zmian zdarzeń (a może nawet inne podejścia), ale ten powinien zacząć od ciebie (a inne są powyżej moich umiejętności i doświadczenia). Podejrzewam, że możesz zacząć od tego „hackish” podejścia i budować odtąd.

Akrobacje
źródło
1
Wielkie dzięki, to naprawdę pomocne. Nagrodzę punkty, jeśli nie zostanie opublikowana lepsza odpowiedź. Jedyne, co mi się nie podoba, to ciągłe odpytywanie, stworzyłem do tego osobne pytanie: askubuntu.com/questions/640741/...
int_ua
1
Odpowiem na to pytanie! Mógłbym skorzystać z tej wiedzy.
Stunts
3
Możesz dodać sleep 0.25na końcu, co stanowi kwadrans opóźnienia. Ułatwia to procesor i nadal działa wystarczająco szybko. Czasami używam tego również we własnych skryptach
Sergiy Kolodyazhnyy
2
ACPI obsługuje słuchawki odłączyć, czy dodasz to do swojej odpowiedzi? askubuntu.com/a/642404/20275
int_ua
Niesamowite! Dzisiaj coś nad tym popracuję.
Stunts