GUI-Requester aus Bashscripten erzeugen

Schnell mal ein Bashscript zusammen gebastelt, daß einen kleinen Job erledigt, machen wohl viele von uns. Blöd ist, daß man das Script vom Desktop aus startet, ohne dem Script irgend etwas mitgeben zu können. Das wäre es doch toll, wenn man den Benutzer elegant fragen könnte, oder?

GUI-Requester aus Bashscripten erzeugen

Im konkreten Fall geht es um ein Script, daß die Tonausgabe eines Programms umschaltet. Die Grundlagen dazu findet Ihr hier:

Twinkle, Twinkle little PVA …

Damit wir den Ton eines Programms umschalten können, müssen wir erstmal wissen, welches Programm gemeint ist und da setzt unser kleines Script an. Da wir vom Desktop reden, wird das tonausgebende Programm ein Fenster offen haben, damit man es bedienen kann.

Jetzt haben wir ein Bashscript gestartet, daß irgendwie mitbekommen muß, welches Fenster denn gemeint ist. Dazu nutzen wir „xprop“ . Xprop erzeugt einen Mauszeiger mit dem man auf das Fenster klicken kann, von dem man alles wissen will, und ich meine echt alles! Das geht sogar soweit, das Defaulticon des Prozesses anzuzeigen, daß zu dem Fenster gehört 😀  Sehr selbst:

XKLAVIER_STATE(INTEGER) = 0, 1654415104
_GTK_EDGE_CONSTRAINTS(CARDINAL) = 85
_NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_FOCUSED
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
_NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 31, 0
_NET_WM_DESKTOP(CARDINAL) = 0
_NET_WM_ALLOWED_ACTIONS(ATOM) = _NET_WM_ACTION_MOVE, _NET_WM_ACTION_RESIZE, _NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_MINIMIZE, _NET_WM_ACTION_SHADE, _NET_WM_ACTION_MAXIMIZE_HORZ, _NET_WM_ACTION_MAXIMIZE_VERT, _NET_WM_ACTION_CHANGE_DESKTOP, _NET_WM_ACTION_CLOSE, _NET_WM_ACTION_ABOVE, _NET_WM_ACTION_BELOW
WM_HINTS(WM_HINTS):
Client accepts input or input focus: True
Initial state is Normal State.
bitmap id # to use for icon: 0x420235a
bitmap id # of mask for icon: 0x4202360
window id # of group leader: 0x4200001
_GTK_THEME_VARIANT(UTF8_STRING) = „dark“
XdndAware(ATOM) = BITMAP
_NET_WM_ICON(CARDINAL) = Icon (48 x 48):

▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓░ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▒░ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓░ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▒ ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▒░░░░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
░ ░
░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

_GTK_WINDOW_OBJECT_PATH(UTF8_STRING) = „/org/gnome/Terminal/window/3“
_GTK_APPLICATION_OBJECT_PATH(UTF8_STRING) = „/org/gnome/Terminal“
_GTK_UNIQUE_BUS_NAME(UTF8_STRING) = „:1.148“
_GTK_APPLICATION_ID(UTF8_STRING) = „org.gnome.Terminal“
_NET_WM_OPAQUE_REGION(CARDINAL) = 0, 0, 1920, 1021
WM_WINDOW_ROLE(STRING) = „gnome-terminal-window-00a05266-8865-460d-9efd-dd4e9d0164db“
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 69215064, 69215065
_NET_WM_USER_TIME_WINDOW(WINDOW): window id # 0x4202357
WM_CLIENT_LEADER(WINDOW): window id # 0x4200001
_NET_WM_PID(CARDINAL) = 7153
WM_LOCALE_NAME(STRING) = „de_DE.UTF-8“
WM_CLIENT_MACHINE(STRING) = „eve.resellerdesktop.de“
WM_NORMAL_HINTS(WM_SIZE_HINTS):
program specified minimum size: 359 by 70
program specified resize increment: 7 by 15
program specified base size: 16 by 26
window gravity: NorthWest
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
WM_CLASS(STRING) = „gnome-terminal-server“, „Gnome-terminal“
WM_ICON_NAME(COMPOUND_TEXT) = „marius@eve:~ — xprop“
_NET_WM_ICON_NAME(UTF8_ST_NET_WM_PID(CARDINAL) = 7153RING) = „marius@eve:~ — xprop“
WM_NAME(COMPOUND_TEXT) = „marius@eve:~ — xprop“
_NET_WM_NAME(UTF8_STRING) = „marius@eve:~ — xprop“

Was wir davon für den Job brauchen, habe ich mal blau markiert. Da steht die PID( ProzessID ) des Programms, das das Fenster aufgemacht hat. Mit folgender Anweisung kann man das im Script auslesen:

pid=$(xprop | grep _NET_WM_PID | grep -o [0-9]*)

Das erste Grep besorgt uns die Zeile, das zweite Grep lässt nur unsere gesuchten Zahlen übrig. Damit haben wir einen Teil der Aufgabe gelöst. Teil Zwei besteht darin, das neue Ausgabegerät für das Programm zu ermitteln.

Damit Ihr versteht, was da als Argumente benutzt wird, ist ein Blick in den anderen Artikel hilfreich. Kurzfassung: Ich habe zwei Ausgänge: Lautsprecher und HDMI(Kopfhörer) .

Mit Zenity können wir beliebige GUI-Requester bauen und das ausgewählte Ergebnis auslesen. Vermutlich ist das Programm bei Euch schon vorinstalliert.

out=$(zenity –list –radiolist –text „Set audio output for window:“ –column „Select“ –column „Output“ FALSE „Lautsprecher“ FALSE „HDMI“ FALSE „Kopfhörer“ )

Das sieht in Real dann so aus:

Mit „–column“ gibt man an, welche Spalten man haben will, dann kommt die Liste der Optionen. Für ein Radiobutton, also eine Liste, wo man nur ein Element ausgewählt haben kann, sind die Optionen so aufgebaut:

FALSE/TRUE Elementname
FALSE/TRUE Elementname
FALSE/TRUE Elementname
FALSE/TRUE Elementname

Wobei TRUE vorausgewählt meint, und FALSE nicht ausgewählt. Im Bashscript stehen die Optionen einfach hintereinander. Hat man etwas ausgewählt, wird es vom Prozess einfach als Text ausgegeben:

[marius@eve ~]$ zenity –list –radiolist –text „Set audio output for window:“ –column „Select“ –column „Output“ FALSE „Lautsprecher“ FALSE „HDMI“ FALSE „Kopfhörer“
Kopfhörer
[marius@eve ~]$

Ich hatte Kopfhörer ausgewählt 😉 Jetzt noch den Prozessnamen:

pname=$( cat /proc/$pid/stat | awk ‚{print $2};‘ | grep -o [a-zA-Z]* )

bauen wir es zusammen:

#!/bin/bash

pid=$(xprop | grep _NET_WM_PID | grep -o [0-9]*)
out=$(zenity –list –radiolist –text „Set audio output for window:“ –column „Select“ –column „Output“ FALSE „Lautsprecher“ FALSE „HDMI“ FALSE „Kopfhörer“ )
pname=$( cat /proc/$pid/stat | awk ‚{print $2};‘ | grep -o [a-zA-Z]* )
pulse.out $pname $out

Fertig. Aber, mit Sonderzeichen im Prozessnamen wird es wohl Probleme geben.

Damit kann man jetzt ein Script starten, das lässt einen ein Fenster auswählen, dann fragt man nach der Tonausgabe und dann wechselt der Ton. Das geht natürlich viel einfacher, wenn man einen Sprachassistenten hat 😀

command:“schalte .* auf .* um“,“EXEC:pulse.outx:x%0x:x%1″

Damit kann man jeden namentlich korrekt erkannten Prozess auf jedes konfigurierte Ausgabegerät umlenken. Hört meine Wort: Das wird Eure Zukunft.

 

 

Kernel 5.3.16 mit HDMI-Audio Problemen

Na klingeln Euch auch noch die Ohren? Mir tun die jetzt noch weh! Wer eine NVIDIA Grafikkarte und einen aktuellen 5.3.16 Kernel einsetzt, der sollte jetzt kein HDMI benutzen.

Kernel Regression durch Patch für eine andere Regression

Es ist immer blöd, wenn der Fehlerfix mehr Probleme macht, als er behebt. So geschehen im neuen 5.3.16 Kernel, wenn man eine NVIDIA Karte hat. Wie Takashi Iwai von Suse dazu schreibt:

The commit e38e486d66e2 („ALSA: hda: Modify stream stripe mask only when needed“) tried to address the regression by the unconditional application of the stripe mask, but this caused yet another
regression for the previously working devices. Namely, the patch clears the azx_dev->stripe flag at snd_hdac_stream_clear(), but this may be called multiple times before restarting the stream, so this
ended up with clearance of the flag for the whole time.

Hat da wohl jemand eine Kleinigkeit nicht bedacht aka die falsche Stelle gepatched 😉 Als Resultat fallen einem fast die Ohren ab, weil die Lautstärke des HDMI Streams so derbe übersteuert klingt, daß selbst 2% Lautstärke nur als Lärm bezeichnet werden können. Ich vermute das hier die Audiodaten im falschen Format angeliefert werden, wo alles was leise wäre, extrem laut ist z.b. LE statt BE Sortierung der Bits.

Die Lösung

Natürlich gibt es eine einfach Lösung für das Problem: 5.3.15 booten oder bis zum nächsten Kernelupdate kein HDMI benutzen 😉

Update:

Laut Laura Abbot von Red Hat wird der Fehler nicht mehr in der 5.3er Serie behoben, was ich bislang bestätigen kann, denn der 5.3.18 hat die gleiche Macke. Es soll stattdessen gleich der 5.4.0 Kernel gebaut werden. Frau Abbot bemüht sich darum, daß der Patch bereits in 5.4.0 einfliesst.

Der Soundbug ist auch unabhängig von den Treibern, aber das habe ich nicht anders erwartet.

Update: wurde in 5.4.5 gefixt.

Linux – Pulseaudio HDMI Sink umbenennen

Im deutschen Fußballspiel bei der WM in Russland ist einiges im Argen, so auch in Pulseaudio 🙂 Seit meinem Upgrade auf Fedora 27 haben meine Pulseaudio Sinks andere Namen bekommen und die sind zum Teil echte Monster 🙂

Sinks auflisten

Schauen wir uns erstmal den Ist-Zustand an :

[marius@eve ~]$ pacmd list-sinks|grep -E „(name:|description)“
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1>
device.profile.description = „Digital Stereo (HDMI 2)“
device.description = „GP107GL High Definition Audio Controller Digital Stereo (HDMI 2)

Wenn man jetzt in der PA Lautstärkenkontrolle die Selectboxen mit den verfügbaren Audioausgängen anklickt, springt einem so ein Name natürlich ins Auge. Viel zu lang 🙂

Das können wir ändern

Dafür gibt es den Befehl „pacmd“ . Der kann einiges mit PA anstellen, aber da wir nur den Namen updaten wollen, ist es eigentlich recht simple:  pacmd befehl option1 option2 …

Wir brauchen als Befehl update-sink-proplist und dazu das Audiodevice das wir ändern möchten und natürlich das Feld, welches wir anpassen müssen.

Beispiel:

pacmd update-sink-proplist alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1 device.description=“HDMI2-(Stereo)“

Wenn man jetzt ein Leerzeichen im Namen haben will, wie das ja wohl möglich sein muß, weil es ja vorher auch drin war, dann hat man ein kleines Problem, denn der Kommandozeilenparser von pacmd hat einen Bug: Er kann keine Leerzeichen verarbeiten 😉

Wenn man das braucht, muß man den Interaktiven Modus wählen:

$ pacmd
Welcome to PulseAudio 11.1-rebootstrapped! Use „help“ for usage information.
>>> update-sink-proplist alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1 device.description=HDMI2 (Stereo)
>>>

Wenn man jetzt in dem Modus „exit“ zum Verlassen der Konsole  eintippt, dann passiert nicht was man erwarten würde, denn „exit“ steht für Pulseaudio-Exit und beendet den Server 😉 Wer da raus will muß mit CTRL+C arbeiten… allgemeines Kopfschütteln ..

Anmerkung:

Das ist leider keine permanente Einstellung, daß muß man nach jedem Start machen.