mgr's weblog

JACK-Input-Plugin für XMMS

December 18, 2005, Music
Last edited on December 18, 2005

Wiki-Seite zum LED-Cube

Anfang der Woche habe ich mir des nächtens endlich ein Input-Plugin für das JACK Audio Connection Kit und XMMS zusammengeschustert. Hauptbeweggrund ist gewesen, daß ich mein XMMS Visualization-Plugin für den LED-Cube für andere, externe Dinge benutzen wollte als nur für Audiodateien, die XMMS selber abspielen kann — besonders, um letztendlich zu Line-in den Kubus blinken lassen zu können, oder was mir gerade einfällt. Ist auch ganz niedlich, wenn er via Mikrophon zur eigenen Stimme oder Geklopfe blinkt.

Noch ein XMMS-Plugin in der abstrusen Programmiersprache C zu schreiben, hatte ich wenig Lust. Auch wollte ich mich weder mit der Plugin-Schnittstelle von XMMS weiter herumschlagen oder mir die Innereien von JACK antun. Ein Ausweg schien das Meta-Input-Plugin aufzuzeigen (die Homepage des Autors, die von der zuvor genannter xmms.org-Seite verlinkt ist, ist wohl seit geraumer Zeit tot, allderings findet man die Datei xmms-meta-input-0.4.tar.gz auch gut per Google). Oh, gerade sehe ich, daß Mikael Bouillot, besagter Autor, wohl umgezogen ist, und sich die Seite nun unter http://www.corbac.com/page3.html findet! Dort finden sich auch alle bisherigen Versionen, — und der Hinweis, man solle inzwischen lieber das BMP-Meta-Plugin von Michael Doering verwenden. Nun, mein Hack baut noch auf das "alte" Plugin auf.

Das nächste Problem war, ein Programm zu finden, das sich am JACK-Server anmeldet und den Sound möglichst als rohen WAV-Stream auf Standard Output herauswirft. jackrec schien zunächst ein geeigneter Kandidat, will allerdings zwingend in eine Datei schreiben. Ein schneller Test mit einer benannten Pfeife ("named pipe" via mkfifo) schlug leider fehl (wäre allerdings auch etwas unergonomsich); ich hatte schon angefangen, jackrec entsprechend umzuschreiben, allerdings habe ich dann gemerkt, daß es auch Blödsinn macht, wenn man es einfach so in eine Datei schreiben löst. Es macht nur eine klitzekleine Datei, die kaum mehr als ein PLIK enthält und bricht ab. Also war dies eine Sackgasse, den ich hatte keine Lust, den Bug in jackrec zu suchen.

Nächster Kandidat schien jack.udp zu sein, ein Client, der zwei jackd-Server per UDP über ein Netzwerk verbindet. Ich wollte auf der einen Seite jack.udp im send-Mode starten, mit Qjackctl verkabeln und den Stream mit dem Allzwecktaschenmesser netcat abfangen. Aber das war natürlich Blödsinn, da am Ende natürlich nicht ein WAV-Stream herauskommt, sondern irgendein JACK-Protokoll. (Nebenbei hat sich herausgestellt, daß jack.udp zwar ein nettes Tool wäre, es allerdings für den Einsatz in einem wirklichen Netzwerk ohne weiteres erst einmal ungeeignet ist. Am Ende kommt nur ein langgezogener, zerknitterter Ton mit vielen Unterbrechungen heraus.)

Als ich schon fast keine Lust mehr hatte (okay, "fast" ist ein Euphemismus), habe ich mir ein paar generelle, nicht JACK-spezifische Audioprogramme für die Kommandozeile genauer angesehen, SoX und co. SoX selbst war zwar nicht geeignet, aber mit Ecasound wurde ich endlich fündig! Ein schneller Test ohne irgendwelche Optimierungen war erfolgreich, anschließend habe ich das ganze noch etwas verschönt und mit allerlei Optionen garniert, damit Ecasound nicht dick puffert (im einzelnen: "-B:rt -b:0 -z:nodb -z:nointbuf").

Hier ist das Ergebnis:

#!/bin/sh # # If one tries to open any file with the extensions ".jack" # it tries to connect to a Jack source with the basename of the filename # (i.e. the filename without path and extension).

case $1 in play) source=$(basename "$(echo -n "$2" | head -c -5)") echo -e "\n======= Connectiong to Jack source: $source =======" 1>&2 # ecasound -q -i jack_auto,"$source" -o stdout ecasound -q -B:rt -b:0 -z:nodb -z:nointbuf -i jack_auto,"$source" -o stdout exit 0 ;; isOurFile) extensions=$(echo -n "$2" | tail -c 5) if [ "x$extensions" == "x.jack" ]; then exit 0 else exit 1 fi ;; esac
exit 1


Rezept

Man lade sich das Meta-Input-Plugin herunter, kompiliert es sich und installiere es (d.h. man packe bei einer Benutzerinstallation einfach die Datei libmetainput.so in sein ~/.xmms/Plugins und erstelle das Verzeichnis ~/.xmms/Plugins/Meta). (Für Eilige gibt es hier auch mein fertiges Binary für die x86er Plattform, natürlich ohne jegliche Garantien, allerdings bin ich ja ein lieber, netter Kerl.)

Die Datei jack-via-ecasound kommt anschließend in das eben erstellte Meta-Verzeichnis, und sollte mit executable flag versehen werden ("chmod +x jack-via-ecasound").


Benutzung

Plugins für XMMS funktionieren in einem Zwei-Schritt-Verfahren. Beim Öffnen einer Datei in XMMS (bzw. Hinzufügen in die Playlist) fragt XMMS die einzelnen Plugins, welches denn bitte für die Datei zuständig ist. Beim Meta-Input-Plugin werden die installierten Skripte dazu mit "isOurFile" als erstes Argument und dem Dateinamen (einschließlich Pfad) als zweites aufgerufen; beim Abspielen schließlich lautet das erste Argument "play", das zweite bleibt der vollständige Dateiname.

Für mein Skript gebe man bitte eine (nicht zwingend vorhandene) Datei mit der Erweiterung ".jack" an, wobei man vor dem Punkt direkt die JACK-Quelle angeben kann. Bei Ecasound kann man idealerweise "jack_auto" als Eingabequelle angeben, wobei der Name (beim Dateinnamen der Teil vor dem Punkt) mit etwas Voodoo auf den eigentlichen JACK-Output gematcht wird. Sehr praktisch!

Mit eingeschaltetem Plugin gebe man also einfach "alsa_pcm.jack" als Dateinamen an und, voila!, XMMS startet beim Abspielen Ecasound, das sich mit der JACK-Quelle "alsa_pcm" verbindet und die Visualization-Plugins blinken zum Ton, der an Line-In hereikommt (so der Mixer der Soundkarte richtig eingestellt ist). Und soll's zu Videos in (G)Mplayer blinken, gebe man einfach "MPlayer.jack" an.

Hach, ich bin glücklich.


Über die beiden JACK-Output-Plugins für XMMS

Es gibt mindestens zwei solcher Plugins: XMMS jack Driver und XMMS Jackasyn Driver. Beide machen so ziemlich das gleiche, das zweite, das die libjackasyn-Bibliothek verwendet, hört sich laut Beschreibung des Debian-Pakets aber besser an:

The advantage of using this plugin is that you do not have to change the output plugin if you want to work with or without jack. The plugin switches automatically between OSS and jack.

Es hat allerdings den gewaltigen Nachteil, daß es — wie auch das OSS-Output-Plugin, von dem wohl fleissig kopiert wurde — immer puffert. Der Standardwert ist dabei gigantische 3 Sekunden! Und der Mindestwert ist nicht etwa 0 Milisekunden, sondern immer noch ordentlich wahrnehmbare 200ms (obwohl es sich nicht wirklich nach 200ms angehört hat). Das ist natürlich reichlich dämlich, wenn man einen low-latency audio server wie eben JACK verwendet. . . Das "normale" JACK-Plugin ohne "asyn" hat dieses Problem nicht.

Trackback pings for this entry are listed below. The URL to ping for this entry is: http://blog.matroid.org/trackback/19

Select a Theme:

Basilique du Sacré-Cœur de Montmartre (Paris) Parc Floral de Paris Castillo de Santa Barbara (Alicante) About the photos

Entries: