Mit etwas Perl ordnet Pidgin – der Tausendsassa unter den Instant-Messaging-Clients – verschiedenen Kommunikationspartnern unterschiedliche Klänge zu und spielt sie zu eintreffenden Nachrichten ab .
Wer während der Arbeitszeit Instant Messaging zur Kommunikation nutzt, hat das Problem, dass die unregelmäßig eintrudelnden Nachrichten die Konzentration stören. Vieles könnte er auch liegen lassen und später bearbeiten. Doch falls ein als Gschaftlhuber bekannter Manager eine Nachricht schickt, ist schnelle Reaktion gefragt. Wie filtert man die dringlichen Nachrichten heraus?
Pidgin, ein Messaging-Client [2], der alle gängigen Kommunikationsprotokolle wie Yahoo Messenger, AOL AIM und IRC kennt, bietet so genannte Buddy Pounces an, die einem eintreffenden Ereignis eine entsprechende Aktion zuordnen. Der dafür zuständige Dialog (Abbildung 1), erreichbar über den Menüpunkt »Tools | Buddy Pounces«, erlaubt es zum Beispiel, beim Versenden einer Message (Ereignis “Sends a message”) oder beim Einloggen eines bestimmten Kommunikationspartners (“Signs on”) eine vordefinierte Sounddatei abzuspielen oder ein externes Programm zu starten.
Dazu gibt man in dem Formular in Abbildung 1 das Protokoll des genutzten IM-Service, den eigenen Account und den Namen des IM-Partners an, bei dessen Aktivität das Ereignis auszulösen ist. Es empfiehlt sich, die Checkbox »recurring« zu aktivieren, sonst wirft Pidgin den Handler genau einmal an und löscht danach dessen Definition.

Abbildung 1: Die Pounce-Funktion in Pidgin führt das Skript »~/bin/pounce-sound« aus, wenn ein Buddy ein Ereignis auslöst.

Abbildung 2: Pidgin legt die konfigurierten Pounces in einer XML-Datei unter dem Verzeichnis ».purple« im Homeverzeichnis ab.
Sounds zum Schlagerpreis
Nun habe ich zufälligerweise vor ein paar Wochen im Kaufrausch bei Amazon.com 500 Soundeffekte als runterladbare MP3-Dateien zum Schlagerpreis von 2,59 US-Dollar erstanden ([3], mittlerweile ist der Preis aber wieder auf 9,49 Dollar hochgeschnellt). Was liegt näher, als sie meinen liebsten IM-Freunden zuzuordnen? Ist das Pidgin-Chatfenster anschließend verdeckt, rüttelt mich nur bei ausgewählten Partnern ein eindeutig zu identifizierendes Geräusch aus der Konzentration. Alle anderen müssen warten.
Der Gschaftlhuber bekommt eine Militärtrompete (»bugle.mp3«) zugeordnet, ein tanzversessener Arbeitskollege eine Samba-Rassel (»cabassa.mp3«) und ein Bekannter auf AIM, der immer den neuesten Tratsch parat hat, ein kurzes Soundschmankerl mit Geschnatter von fliegenden Wildgänsen (»goose.mp3«).
Allerdings hatte ich keine Lust, alles einzeln von Hand in Pidgins Dialogfelder einzutragen und dies bei jeder weiteren Pidgin-Instanz zu wiederholen, auf dem Netbook und zu Hause. Zum Glück legt Pidgin die Pounce-Definitionen aber in einer leicht lesbaren XML-Datei unter »~/.purple/pounces.xml« ab.
Das Perl-Skript »pounce-yml-to-xml« nimmt eine kompakt formatierte YAML-Datei wie in Abbildung 3 und wandelt sie ohne viel Federlesen in das viel umständlichere, aber von Pidgin favorisierte XML-Format um. Die YAML-Datei »pounces.yml« liegt unter einem neu angelegten Verzeichnis »~/.pidgin-pounces« und dort trägt der Benutzer für jeden seiner Online-Buddies eine Sounddatei ein.

Abbildung 3: Aus den Daten dieser YAML-Datei generiert das Skript »pounce-yml-to-xml« die XML-Datei in Abbildung 5.
Tanz auf allen Hochzeiten
Da Pidgin verschiedenste IM-Protokolle benutzt und ein Anwender meist unter mehreren Accounts auf mehreren Servern gleichzeitig eingeloggt ist, steht unter dem Eintrag »sound_map« in der YAML-Datei zuerst ein Schlüssel, der den jeweiligen IM-Anbieter und den dort verwendeten Nutzernamen durch einen Doppelpunkt getrennt auflistet.
Unter dieser Hierarchiestufe folgen die Zuordnungen von Onlinepartnern und Sounddateien, die Pidgin abspielen soll, falls der Partner sich einloggt oder dem Nutzer eine Nachricht schickt. Nach Abbildung 3 ist also mein Screen-Name auf Yahoos Messenger-Service »mikeschilli« und falls mir dort »elcaramba« eine Nachricht schickt, rasselt Pidgin mit »cabassa.mp3« einen heißen südamerikanischen Rhythmus.
Filter gegen Trommelfeuer
Neben der Zuordnung der Buddies zu den Geräuschen unter dem Eintrag »sound_map« setzt die YAML-Datei auch noch den Parameter »interval«, damit das System nicht bei jeder eintrudelnden Nachricht ein Geräusch abspielt. Steht »interval« auf 60, ist die Mindestzeitspanne zwischen zwei Geräuscheinspielungen 60 Sekunden. Kommen in diesem Zeitraum mehrere Nachrichten an, unterdrückt das System das abzuspielende Geräusch, denn schließlich soll der arme User kein akustisches Trommelfeuer ertragen, sondern arbeiten.
YAML-Daten lassen sich eins zu eins in Perl importieren, die Funktion »LoadFile()« aus dem YAML-Modul wandelt sie in die in Abbildung 4 gezeigte Struktur um. In dem darauf folgenden Schritt steht nun die Konvertierung der Daten in aufgeblähtes XML an.

Abbildung 4: Mit »LoadFile()« eingelesen ergeben die YAML-Daten aus der Abbildung 3 diese Datenstruktur in Perl.
Von YAML nach XML
Das von Pidgin verwendete XML-Format (Abbildung 2) definiert für jeden Pounce ein Konstrukt, das in »<pounce>«-Tags eingeschlossen ist. Die Gesamtheit aller dieser Tags steht innerhalb eines Sammel-Tags mit dem Namen »<pounces>«. Dies ist einfach mittels Reverse Engineering herauszufinden, in dem man mehrere Pounces mit Pidgins grafischer Oberfläche definiert und anschließend die automatisch neu geschriebene XML-Datei inspiziert.
Das Skript »pounce-yml-to-xml« in Listing 1 wandelt nun die kompakte YAML-Datei in Abbildung 3 in ausführliche XML-Instruktionen für Pidgin um, die es anschließend in »~/.purple/pounces.xml« speichert. Die For-Schleife ab Zeile 17 iteriert über die Einträge im »sound_map«-Hash der YAML-Datei, die allesamt im Format »protocol:account« vorliegen. Darunter befindet sich ein weiterer Hash, der den Onlinepartnern (Buddies) Geräusche zuordnet.
|
Listing 1: |
|---|
01 #!/usr/local/bin/perl -w
02 use strict;
03 use Sysadm::Install qw(:all);
04
05 use YAML qw(LoadFile);
06 use Template;
07
08 my($home) = glob "~";
09 my $path = "$home/.pidgin-pounce";
10 my $yaml = LoadFile( "$path/pounce.yml" );
11
12 my $xml_file = "$home/.purple/pounces.xml";
13 my $SOUND_CMD = "~/bin/pounce-sound";
14
15 my @pounces = ();
16
17 for my $account (
18 keys %{ $yaml->{sound_map} }) {
19
20 my($proto, $recv) = spl it /:/, $account;
21
22 for my $buddy (keys %{
23 $yaml->{sound_map}->{$account} }) {
24
25 push @pounces,
26 mk_pounce($buddy, $recv, $proto);
27 }
28 }
29
30 binmode STDOUT, ":utf8";
31
32 my $xml = q{
33 <?xml version='1.0' encoding='UTF-8' ?>
34 <pounces version='1.0'>
35 [% FOR pounce IN pounces %]
36 [% pounce %]
37 [% END %]
38 </pounces>
39 };
40
41 my $tmpl = Template->new();
42
43 mv $xml_file, "$xml_file.old" if
44 -f $xml_file;
45
46 $tmpl->process( $xml,
47 { pounces => @pounces },
48 $xml_file ) or die $tmpl->error;
49
50 ###########################################
51 sub mk_pounce {
52 ###########################################
53 my($buddy, $recv, $prot) = @_;
54
55 return qq{
56 <pounce ui='gtk-gaim'>
57 <account
58 protocol='prpl-$prot'>$recv</account>
59 <pouncee>$buddy</pouncee>
60 <options/>
61 <events>
62 <event type='sign-on'/>
63 <event type='message-received'/>
64 </events>
65 <actions>
66 <action type='execute-command'>
67 <param name='command'
68 >$SOUND_CMD $prot:$recv $buddy</param>
69 </action>
70 </actions>
71 <save/>
72 </pounce>
73 }
74 }
|
Die Keys-Funktion gibt eine Liste dieser Partner zurück. Zeile 26 ruft für jeden die ab Zeile 51 definierte Funktion »mk_pounce()« auf. Als Parameter erhält sie den Namen des Buddy, den Namen des Accounts (»recv« genannt, weil dieser später Nachrichten von den Buddies empfängt) sowie das verwendete Protokoll (»yahoo«, »aim« oder dergleichen). Die Funktion gibt dann jeweils einen XML-String zurück, der einem Eintrag in Pidgins Konfigurationsdatei »pounces.xml« entspricht.
Empfindlicher Pidgin
Zum Schreiben des XML-Formats der Gesamtdatei kommt das Modul Template vom CPAN zum Einsatz, ein Template-Prozessor, der normalerweise beim dynamischen Aufbau von Webseiten hilft. Im Skript »pounce-yml-to-xml« expandiert es nur Makros im Format »[% Variable %]«. Das praktische »FOR«-Konstrukt der Template-Sprache hilft in Zeile 35, die unästhetische Vermengung von Perl- und XML-Code zu vermeiden.
Erst habe ich dafür ein wenig mit XML::Simple experimentiert, aber damit XML zu erzeugen, das genauso aussieht wie die Vorgabe, ist praktisch unmöglich. Und Pidgin ist nicht gerade robust, was die Abfolge der Daten in dieser XML-Datei betrifft. Wer einen gnadenlos abstürzenden Pidgin beobachten will, braucht nur den »pouncee«-Eintrag vom Anfang ans Ende der »pounce«-Struktur zu verfrachten.
Die Funktion »mv« aus dem Modul Sysadm::Install schiebt eine eventuell schon von Pidgin verwaltete Datei »pounces.xml« höflich zur Seite und benennt sie in »pounces.xml.old« um. Die »process()«-Methode in Zeile 46 nimmt einen Array von Pounce-XML-Texten entgegen, über den die For-Schleife im Template-Code iteriert, das parametrisierte XML an die richtigen Stellen einpflanzt und anschließend Pidgins Datei »pounces.xml« mit den neuen Daten überschreibt.
Das Ergebnis, das in Abbildung 5 zu sehen ist, enthält einen Wust aus XML-Statements für jede Kombination aus Protokoll, Account und Kommunikationspartner. Am Ende rufen aber alle Instanzen dieses XML-Snippets das externe Programm »pounce-sound« (Listing 2) mit Parametern wie Account- und Username auf.
|
Listing 2: |
|---|
01 #!/usr/local/bin/perl -w
02 use strict;
03 use YAML qw(LoadFile);
04 use Data::Throttler;
05
06 my($proto, $buddy) = @ARGV;
07
08 die "usage: $0 proto:recv buddy"
09 if !defined $buddy;
10
11 my($home) = glob "~";
12 my $path = "$home/.pidgin-pounce";
13
14 my $yaml = LoadFile( "$path/pounce.yml" );
15
16 my $throttler = Data::Throttler->new(
17 max_items => 1,
18 interval => $yaml->{interval},
19 backend => "YAML",
20 backend_options => {
21 db_file => "$path/throttle.yml",
22 },
23 );
24
25 if(! $throttler->try_push(
26 key => "$proto:$buddy")) {
27 # rate limit reached, skip it
28 exit 0;
29 }
30
31 if(exists
32 $yaml->{sound_map}->{$proto}->{$buddy}) {
33 my $sound =
34 $yaml->{sound_map}->{$proto}->{$buddy};
35 system("play $path/sounds/$sound");
36 }
|

Abbildung 5: Das von »pounce-yml-to-xml« generierte XML, das Pidgin dazu veranlasst, bei eintreffenden Nachrichten von »bigboss« an »mikeschilli« das externe Skript »pounce-sound« aufzurufen.
Die den Online-Buddies zugeordneten Geräuschdateien installiert man allesamt im Verzeichnis »sounds« unterhalb des ».pidgin-pounces«-Directory.
Sound zurechtschneiden
Ihre Dauer sollte jeweils ein paar Sekunden nicht überschreiten. Wer eine längere Sounddatei kürzen möchte, greift zu Audacity und blendet mit den Fade-in- und Fade-out-Effekten das Geräusch einfach sanft ein- und aus (Abbildung 6).

Abbildung 6: Das Tool Audacity schneidet das Geräusch auf die korrekte Länge zurecht und kann es mit den Fade-in- oder Fade-out-Effekten sanft ein- oder ausklingen lassen.
Das von Pidgin im Ereignisfall aufgerufene Skript »pounce-sound« nimmt auf der Kommandozeile als Parameter die Kombination aus Protokoll und Account sowie das Kürzel des sendenden Users entgegen. Es liest die YAML-Datei ein und findet heraus, ob ein Spezialsound für den jeweiligen User vorliegt. Falls ja, spielt es diesen mit dem Utility »play« über die Soundkarte ab.
Erhält Pidgin zum Beispiel über das Yahoo-Protokoll mit dem eingeloggten User »mikeschilli« eine Nachricht vom User »bigboss«, dann ruft es
pounce-sound yahoo:mikeschilli bigboss
auf. Das Skript wiederum sieht in der YAML-Datei nach, findet, dass für diesen Fall die MP3-Datei »bugle.mp3« vorgesehen ist, und spielt sie ab.
Das einzig Bemerkenswerte an »pounce-sound« ist der Aufruf von Data::Throttler, der verhindert, dass zu häufiges Abspielen der Sounds den Zorn des Benutzers erregt. Data::Throttler legt unter »~/.pidgin-pounce/throttler.yml« eine YAML-Datei an und merkt sich dort Anzahl und Zeitpunkt der letzten Aufrufe. Die Methode »try_push()« behält einen Schlüssel aus Protokoll, dem Accountnamen und dem Namen des sendenden Buddy und liefert einen unwahren Wert zurück, falls der Buddy während der Zeitspanne der letzten »interval« Sekunden schon aktiv war. Andere Kommunikationspartner hingegen lässt es gewähren, bis auch diese ihr Quantum überschreiten.
Installation
Das von Pidgin im Ereignisfall aufgerufene Skript »pounce-sound« wandert ins »bin«-Verzeichnis unterhalb des Homeverzeichnisses. Das Kommando »chmod +x« macht es ausführbar. Die CPAN-Module YAML, Template und Sysadm::Install liegen vielen Distributionen bei und lassen sich mit deren Packagemanager installieren. Das Modul Data::Throttler richtet sich der Anwender über eine CPAN-Shell mit »perl -MCPAN -e’install Data::Throttler’« ein. Das Utility »play«, mit dem das Skript »pounce-sound« die MP3-Datei abspielt, ist Bestandteil des Pakets »sox«, das der erfahrende Ubuntu-Administrator mit »sudo apt-get install sox« installiert.
Die eventuell noch gekürzten und weich ein- und ausklingenden Sounddateien wandern ins Unterverzeichnis »sounds«. Dann gilt es, die YAML-Datei in Abbildung 2 an die lokalen Verhältnisse anzupassen, den eventuell laufenden Pidgin-Prozess zu stoppen und das Skript »pounce-yml-to-xml« aufzurufen. Wer den eingestellten Sound nur bei eingehenden Nachrichten hören möchte und nicht, wenn der Buddy sich einloggt, löscht den »sign-on«-Event im XML in Zeile 62 von Listing 1.
Nach einem Neustart schnappt Pidgin sich die automatisch erzeugte XML-Datei und zeigt die neue Konfiguration auf Abfrage an, wie in Abbildung 7 gezeigt. Bei jedem vorgemerkten Ereignis führt Pidgin den dazu definierten Pounce aus und ruft etwa das Soundskript auf, das die Militärtrompete erschallen lässt, die den Anwender aus dem Büroschlaf schreckt. Jaja, Boss, bin praktisch fertig!

Abbildung 7: Pidgin hat sich die XML-Datei geschnappt und zeigt im Pounce-Dialog die automatisch generierten Einstellungen an.
|
Infos |
|---|
|
[1] Listings zu diesem Artikel: [ftp://www.linux-magazin.de/pub/listings/magazin/2010/02/Perl ] [2] Pidgin: [http://www.pidgin.im ] [3] “500+ Sound Effects” als MP3 bei Amazon: [http://www.amazon.com/gp/product/B002OVD5FK] |






