Musik, lecker angerichtet
Shell-Skripte mit grafischen Dialogen
Es wird angerichtet!
cat ~/.mp3liste gibt die Datei ~/.mp3liste Zeile für Zeile aus. Damit kdialog --checklist an diese Daten herankommt, bedienen wir uns eines Kunstgriffs: Wir leiten die Ausgabe von cat mit dem Pipeline-Operator | an den Befehl xargs weiter:
cat ~/.mp3liste | xargs -l$max_line kdialog --checklist "Bitte wählen Sie die gewünschten Songs aus."
Dieser konvertiert die einzelnen übergebenen Zeilen derart, dass sie sich als Parameter des nachfolgenden Befehls nutzen lassen, also praktisch ans Ende des kdialog-Kommandofragments angehängt werden. Ein solcher Schritt ist bei der bash leider notwendig, da ansonsten Probleme mit dem Zeilenendezeichen, das in Dateien verwendet wird, auftreten. Außerdem kümmert sich xargs auch um den Schutz von Sonderzeichen vor der Interpretationswut der Shell.
Der xargs-Parameter -l$max_line sollte eigentlich nicht notwendig sein. Er gibt an, wieviele Zeilen xargs tatsächlich berücksichtigen soll. Bei Tests stellte sich aber heraus, dass es ohne ihn häufig zu Speicherzugriffsfehlern kam.
Doch das hat nun wirklich nichts mehr mit kdialog zu tun. Ein paar weitergehende Erklärungen zu den in den Listings gezeigten Shell-Skripten bietet Kasten 1, während Tabelle 1 nicht nur die darin verwendeten kdialog-Dialoge noch einmal zusammenfasst, sondern auch ein paar weitere Anregungen zum Ausprobieren gibt.
Kasten 1: Ausflug in die Shell-Programmierung
Um mit kdialog zu arbeiten, muss man nicht alle Code-Zeilen aus Listing 1 wirklich verstehen – und Listing 2 spielt in diesem Zusammenhang überhaupt keine Rolle. Dennoch lässt sich daraus das eine oder andere zum Thema Shell-Programmierung lernen. Betrachten wir diese Zeilen daher noch einmal etwas genauer: Die Bedingung
if test $exitstatus -eq 0
sorgt in Listing 1 dafür, dass die Auswahl des Mediaplayers und der abzuspielenden Songs nur dann erfolgt, wenn die Variable exitstatus gleich ("equal") 0 ist. Das ist der Wert, mit dem wir die Variable zu Beginn
exitstatus=0
gefüllt haben. Konnte die ~/.mp3liste nicht erzeugt werden, setzen wir ihn im Verlauf des weiteren Skripts auf 1. Damit erscheinen die beiden Auswahldialoge nur dann, wenn eine nicht-leere Songliste zur Verfügung steht.
Wie am Ende des Artikels erwähnt, mussten wir xargs mit der Anzahl der zu verarbeitenden Zeilen (-l$max_line) aufrufen. Diese holt sich die Shell aus der Variablen max_line. Doch woher nimmt die ihren Inhalt?
max_line=`wc -l ~/.mp3liste | sed s/[" "]*/""/ | cut -d " " -f 1`
ermittelt den passenden Wert und legt ihn in max_line ab: wc -l ~/.mp3_liste ermittelt die Anzahl von Zeilen ("lines") in der Datei ~/.mp3liste. Leider stellt wc seiner Ausgabe Leerzeichen voran:
$ wc -l ~/.mp3liste
300 /home/hoepfner/.mp3liste
Diese entfernt sed. Mit dem darauf folgenden s signalisieren wir, dass sed die Zeichenkette, die wir zwischen den ersten beiden / definieren, durch diejenige ersetzen soll, die zwischen dem mittleren und dem letzten Schrägstrich steht. Bei [" "]* handelt es sich um einen regulären Ausdruck, der für eine Folge von Leerzeichen steht: In [] geben wir alle in Frage kommenden Zeichen an (die Anführungszeichen schützen das Leerzeichen lediglich); * signalisiert: "Nimm die gesamte Zeichenfolge, die nur aus diesen Zeichen besteht." Die erste auf der Zeile gefundene Folge aus null oder mehreren Leerzeichen ersetzt sed nun durch nichts ("").
Damit beginnt die Zeile jetzt mit der gewünschten Zahl. Den von wc angehängten Dateinamen schneidet cut einfach weg: Es teilt die Ausgabe anhand eines Trennzeichens (in unserem Fall dient das Leerzeichen als "Delimiter": -d " ") in Spalten auf und gibt mit -f 1 nur die erste Spalte, also die mit der Zahl, wieder aus.
Sind die Songs einmal ausgewählt, startet
eval $player $songs
das gewünschte Wiedergabeprogramm: Die Variable player wurde ja mit dem Rückgabewert des Player-Dialogs gefüttert, und dabei handelt es sich um das Kommando zum Aufruf des ausgewählten Players (z. B. xmms). Die zweite Variable enthält eine Liste der abzuspielenden MP3-Dateien. eval führt nun das, was es als ersten Parameter übergeben bekommen hat, aus und übergibt dabei die Songliste als Argument. Wurde das X-Multimedia-System ausgewählt, startet eval demnach den Befehl xmms mit vielen, vielen Dateinamen.
Was tut <C>mp3infos.bash<C>?
Das Hilfsskript aus Listing 2 prüft zunächst, ob es die Datei, die es beim Aufruf als erstes Argument mit bekommt, lesbar ist (test -r "$1"). Ist das der Fall, gibt es diesen Namen mit echo noch einmal aus, setzt ihn dabei aber in Anführungsstriche ("). Mit dem vorangestellten \ sagt es dabei der Shell: "Finger weg, dieses " ist nicht in der Shell-Sonderbedeutung, sondern buchstäblich gemeint."
echo -n \" gibt auf einer neuen Zeile ein weiteres " aus, sorgt mit -n aber dafür, dass die Zeile anschließend nicht umbrochen wird. Somit kann mp3info seine Informationen zu der Datei in der Spezialvariablen 1 auf dieselbe Zeile schreiben.
mp3info soll diese dank -p speziell formatiert ausgeben: Zunächst den Interpreten (%a – "artist), dann ein Strich, dann den Titel (%t), anschließend in Klammern die Bitrate %r, einen Trennstrich und den Dateinamen und zu guter Letzt ein weiteres Anführungszeichen. Den Dateinamen erhalten wir, indem basename die Verzeichnisangaben zur Datei wegschneidet.
Zum Schluss sorgt echo für einen Zeilenumbruch in der mp3infos.bash-Ausgabe, und ein letztes echo schreibt den Wert off auf die letzte Zeile.
Dass all diese Angaben in ~/.mp3liste landen, dafür sorgt das Hauptskript mp3finder.bash mit der Ausgabeumleitung >> ~/.mp3liste.
Listing 1
heißt das eigentliche Programm
#!/bin/bash
exitstatus=0
# Aufbau der MP3-Liste in ~/.mp3liste
if test ! -r ~/.mp3liste || kdialog --yesno "Soll die mp3-Liste neu geladen werden?"
then
pfad=`kdialog --inputbox "Wo soll die Suche starten ?" "$HOME"`
rm -f ~/.mp3liste
if ! find $pfad -type f -iname "*.mp3" -exec ./mp3infos.bash {} \; 2> /dev/null >> ~/.mp3liste
then
kdialog --error "mp3-Liste konnte nicht erzeugt werden."
exitstatus=1
fi
fi
if test -s ~/.mp3liste
then
kdialog --msgbox "Die mp3-Liste wurde erfolgreich angelegt."
else
kdialog --sorry "Es wurden keine mp3-Dateien gefunden."
exitstatus=1
fi
# Aufbauen der Auswahlliste
if test $exitstatus -eq 0
then
if player=`kdialog --menu "Bitte wählen Sie einen der folgenden Player:" xmms "X-Multimedia-System" noatun noatun`
then
max_line=`wc -l ~/.mp3liste | sed s/[" "]*/""/ | cut -d " " -f 1`
if songs=`cat ~/.mp3liste | xargs -l$max_line kdialog --checklist "Bitte wählen Sie die gewünschten Songs aus."`
then
eval $player $songs
fi
fi
fi
Listing 2
macht die Arbeit im Hintergrund
#! /bin/bash
if test -r "$1"
then
echo \"$1\"
echo -n \"
dateiname=`basename "$1"`
mp3info -p "%a - %t (%r - $dateiname)\"" "$1"
echo
echo "off"
fi
Tabelle 1: kdialog-Dialogtypen und Parameter
| Aufruf | Bedeutung |
|---|---|
kdialog --yesno text
|
Rückfrage mit Ja-Nein-Knöpfen |
kdialog --yesnocancel text
|
Rückfrage mit Ja-Nein-Abbrechen-Knöpfen |
kdialog --warningyesno text
|
Warnung mit Ja-Nein-Knöpfen |
kdialog --warningcontinuecancel text
|
Warnung mit Fortfahren-Abbrechen-Knöpfen |
kdialog --warningyesnocancel text
|
Warnung mit Ja-Nein-Abbrechen-Knöpfen |
kdialog --sorry text
|
"Bedaure"-Nachricht |
kdialog --error text
|
Fehlermeldung |
kdialog --msgbox text
|
Benachrichtigung |
kdialog --inputbox text default
|
Eingabefeld (default legt bei Bedarf einen Ausgangswert fest)
|
kdialog --password text
|
Passwort-Dialog (die Eingabe wird durch Sterne maskiert) |
kdialog --textbox file breite hoehe
|
Textfeld-Dialog (stellt den Inhalt der Datei filedar; mit breite und hoehe dürfen optional die Abmessungen des Fensters in Pixeln angegeben werden)
|
kdialog --menu text rueck1 eintrag1 rueck2 eintrag2 ...
|
Menü-Dialog mit der Überschrift text und mindestens einem Menüeintrag, der aus jeweils zwei Teilen besteht: eintrag legt den Namen des Menüeintrags fest, rueck definiert den Rückgabewert des Dialogs, wenn dieser Menüeintrag gewählt wurde
|
kdialog --checklist text rueck1 eintrag1 status1 ...
|
Ankreuzliste, aus der im Gegensatz zum Menü mehrere Einträge ausgewählt werden dürfen; die Parameter entsprechen denen des Menü-Dialogs; hinzu kommt status, das mit dem Wert on eine Vorauswahl erlaubt
|
kdialog --separate-output --checklist text rueck1 eintrag1 status1 ...
|
Wie oben; allerdings erfolgt die Ausgabe auf der Kommandozeile bei Mehrfachauswahl zeilenweise |
kdialog --radiolist text rueck1 eintrag1 status1 ...
|
Auswahldialog, bei dem nur eine Anwahl möglich ist; die Parameter entsprechen denen der Checkliste |
Der optionale Parameter --title text setzt die Titelzeile des kdialog-Fensters auf text
|
Der Autor
Hagen Höpfner ist wissenschaftlicher Mitarbeiter am Institut für Technische und Betriebliche Informationssysteme der Fakultät für Informatik an der Otto-von-Guericke-Universität Magdeburg. Was er dort so alles treibt, kann http://wwwiti.cs.uni-magdeburg.de/~hoepfner/ entnommen werden. In seiner Freizeit spielt der begeisterte Vater Gitarre in der Rockband "Gute Frage" (http://www.gutefrage.de/).
Glossar
Shell-Skripte
Bei der Shell handelt es sich um das Programm, das die "Kommandozeile" bereitstellt und es so ermöglicht, dem Betriebssystem Aufträge zu geben. Obwohl man unter Linux standardmäßig auf die "Bourne Again Shell" Bash trifft, gibt es die Möglichkeit, ein anderes Programm für diesen Zweck zu verwenden. Moderne Shells haben in der Regel die Funktionalität einer Programmiersprache eingebaut, so dass man Befehle, die man auf der Kommandozeile eingibt, auch zu ganzen Programmen, den Shell-Skripten, kombinieren kann, wie zum Beispiel der Workshop [6--11] zeigt.
GUI-Toolkit
Eine Programmierbibliothek ("Library"), die wie ein Werkzeugkasten Bausteine zum Aufbau grafischer Benutzerschnittstellen ("Graphical User Interfaces") – Menüs, Buttons, Auswahlknöpfe usw. – zur Verfügung stellt.
Kernel-Konfiguration
Das eigentliche Linux-Betriebssystem, den Kernel, kann man aus dem Quellcode selbst erstellen und dessen Funktionalität damit speziell an eigene Bedürfnisse anpassen. Für diese Aufgabe liefern die Kernel-Entwickler eigens ein "Konfigurationsprogramm" mit, das man im Quellcode-Verzeichnis des Kernels mit "make config" im Textmodus, mit "make menuconfig" mit pseudografischer Oberfläche und mit "make xconfig" mit grafischem Frontend aufruft. Das Prozedere ändert sich mit der nächsten Kernel-Generation 2.6.
Zusatzinformationen in MP3-Dateien, die Auskunft über Titel, Interpret, Album und ähnliches geben. mp3info unterstützt nur die ältere, aber für die meisten Zwecke ausreichende Version ID3v1, die lediglich eine Handvoll Spezialtags von je maximal 30 Zeichen Länge kennt.
Kommandosubstitution
Schreibt man ein Shell-Kommando zwischen zwei sogenannte Backticks (``, also zwei Grave-Akzente von links oben nach rechts unten), führt die Shell dieses Kommando zuerst aus und ersetzt es (Backticks inklusive) durch seine Ausgabe. Erst anschließend führt sie das so entstandene, gesamte Kommando aus. So enthält die Variable v nach dem Befehl "v=hostname" den Wert "hostname"; nach "v=`hostname`" hingegen den Namen des Arbeitsrechners.
HOME
Eine vordefinierte Umgebungsvariable, aus der man in der Shell jederzeit das jeweilige Home-Verzeichnis erfragen kann.
Infos
[1] XDialog: http://xdialog.dyns.net/
[2] Dialog: http://hightek.org/dialog/
[3] GDialog: http://www.gnu.org/directory/gnomeutils.html
[4] Mp3info: http://ibiblio.org/mp3info/
[5] Bash: http://www.gnu.org/software/bash/bash.html
[6] Mirko Dölle: "Hallo Welt", LinuxUser 12/2000, S. 38 ff., http://www.linux-user.de/ausgabe/2000/12/038-pcorner/pcorner1.html
[7] Mirko Dölle: "Im Märzen der Bauer…", LinuxUser 01/2002, S. 48 ff., http://www.linux-user.de/ausgabe/2001/01/048-pcorner/pcorner2.html
[8] Mirko Dölle: "Wortfetzen", LinuxUser 02/2001, S. 49 ff., http://www.linux-user.de/ausgabe/2001/02/049-pcorner/pcorner3.html
[9] Mirko Dölle: "Ihre Papiere bitte…", LinuxUser 04/2001, S. 58 ff., http://www.linux-user.de/ausgabe/2001/04/058-pcorner/pcorner4.html
[10] Mirko Dölle: "Checkpoint Charlie", LinuxUser 05/2001, S. 48 ff., http://www.linux-user.de/ausgabe/2001/05/048-pcorner/Kontrollstrukturen-2.html
[11] Mirko Dölle: "Baukastensystem", LinuxUser 07/2001, S. 52 ff., http://www.linux-user.de/ausgabe/2001/07/052-pcorner/pcorner6.html
[12] Patricia Jung: "Vorfreude, schönste Freude", LinuxUser 12/2001, S. 85 ff., http://www.linux-user.de/ausgabe/2001/12/085-adventskalender/adventskalender.html
[13] Sibylle Nägle: "Ein Kleid für die Kommandozeile", Linux-Magazin 04/2000, S. 120 ff., http://www.linux-user.de/ausgabe/2000/06/TclTk1/tcl1.html
[14] Christian Perle: "Frage und Antwort", LinuxUser 11/2001, S. 78 f., http://www.linux-user.de/ausgabe/2001/11/078-ootb/dialog-4.html



