#!/usr/bin/perl -w #------------------------------------------------------------------------------- # MPD_LCD - Get Special Infos from MPD for Displaying on LCD # # Creation: 17.03.2005 LeSpocky # Last Update: 24.04.2005 LeSpocky # Revision: v0.1.4 # # Copyright (c) 2005 Alexander Dahl # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. #------------------------------------------------------------------------------- # Verwendung # ---------- # Beim Aufruf verlangt das Skript drei Parameter: als erstes, welche Info # erwünscht ist ('t' für title oder 'a' für artist), dann die Länge der # möglichen Zeile und als drittes 'l' für linksbündig oder 'z' für zentriert # Bei mehr, weniger oder falschen Parametern wird Fehlermeldung zurückgegeben. # Sonst kommt eben Title oder Artist auf die Länge formatiert zurück. # # Beispiel für zentrierte Ausgabe des Titels auf eine Länge von 24 Zeichen: # mpdlcd t 24 z #------------------------------------------------------------------------------- use strict; use IO::Socket; my $host = 'localhost'; my $port = 6600; # wenn die als Umgebungsvariablen vorliegen, besser die Umg.-Var. nehmen $host = $ENV{MPD_HOST} if ($ENV{MPD_HOST}); $port = $ENV{MPD_PORT} if ($ENV{MPD_PORT}); sub ftrim($) { # string übergeben # befreit den übergebenen string von zeugs an anfang und ende my $str = shift; $str =~ s/^\s+//; $str =~ s/\s+$//; return $str; } sub fsomespaces($) { # wieviel spaces zurück? # gibt einen string aus x leerzeichen zurück my $str = ''; my $i = 0; for ($i = 0; $i < $_[0]; $i++) { $str = $str.' '; } return $str; } sub fstrtolen($$$) { # string, dann länge, dann 0 linksbündig 1 zentriert # string auf ne definierte länge bringen (lcd hat ja eine zeile mit definierter # anzahl an zeichen. d.h. wenn zu lang, letzten drei zeichen punkte, wenn zu # kurz, rest mit leerzeichen auffüllen) my $str = $_[0]; my $lenshould = $_[1]; my $lz = $_[2]; my $lenis = length($str); my $lenbuf; my $buf1; my $buf2; if (($lenis < $lenshould) and $lz) { $lenbuf = ($lenshould - $lenis) / 2; $buf1 = fsomespaces($lenbuf - 1); $buf1 = $buf1.' ' unless (($lenshould - $lenis) % 2); $buf2 = fsomespaces($lenbuf); $str = $buf1.$str.$buf2; } elsif (($lenis < $lenshould) and not $lz) { $buf1 = fsomespaces($lenshould - $lenis); $str = $str.$buf1; } else { $str = substr($str, 0, $lenshould - 3)."..."; } return $str; } sub fanstohash($$) { # connectionhandler und dann zu übergebender string # liest alles aus der übergebenen connection, schreibt's in ein Hash und gibt # das dann zurück (wir wissen ja, wie der MPD auf unsere Befehle antwortet) my $conn = $_[0]; # das sollte der handler für die connection sein my $order = $_[1]; # und das soll er machen my $result = ''; my %myhash; print $conn $order; while (ftrim($result) ne "OK") { $result = <$conn>; $result =~ m/: /; # die Infos sind durch ': ' getrennt # Hash: was vor dem ersten ': ' stand wird key, das andere value :hop: $myhash{ftrim($`)} = ftrim($'); # wenn Titel oder Artist fehlen (ID-Tag) "Unbekannt" setzen if (!$myhash{Title}) {$myhash{Title} = 'Unbekannt';} if (!$myhash{Artist}) {$myhash{Artist} = 'Unbekannt';} } return %myhash; } #------------------------------------------------------------------------------- ### main() ;-) my $lcdlength = 16; # einfach mal als Default-Wert angenommen ;-) my $reqinfo = ''; my $align = ''; my $connection; my $trash; # kommandozeilenparameter prüfen und in die richtigen variablen speichern if ((@ARGV == 2) or (@ARGV == 3)) { $reqinfo = ftrim($ARGV[0]); unless (($reqinfo eq 't') or ($reqinfo eq 'a')) { print fstrtolen('Parameter nicht unterstützt', $lcdlength, 0); exit; # Skript nützt so nix, also raus hier } $lcdlength = ftrim($ARGV[1]); if ($ARGV[2]) { $align = ftrim($ARGV[2]); } unless ($align eq 'z') { $align = 0; } else { $align = 1; } } else { print fstrtolen('Falsche Anzahl Parameter', $lcdlength, 0); exit; # Skript nützt so auch nix, also raus hier } # MPD ist ein Server und dahin verbinden wir uns jetzt $connection = IO::Socket::INET->new ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp') or $connection = 0; if ($connection) { # wenn connection zum mpd erfolreich # erste ausgabe vom MPD nach etablierung der connection abfangen und # weg damit in diese dummy-variable ;-) $trash = <$connection>; # erstmal den Status abfragen, um zu gucken ob der Player überhaupt läuft my %answer = fanstohash($connection, "status\n"); if (($answer{state} eq 'play') or ($answer{state} eq 'pause')) { # wenn der Player läuft, wollen wir den Song wissen: %answer = fanstohash($connection, "currentsong\n"); if ($reqinfo eq 'a') { # je nach Kommandozeilenargument eben # hier Konvertierung von Unicode einfügen ;-) # $answer{Artist} =~ tr/\0-\x{ff}//UC; print fstrtolen($answer{Artist}, $lcdlength, $align); } elsif ($reqinfo eq 't') { print fstrtolen($answer{Title}, $lcdlength, $align); } else { # wurde eigentlich oben schon abgefangen bei Überprüfung # der Kommandozeilenparameter print fstrtolen('Parameter nicht unterstützt', $lcdlength, $align); } # hat noch Probleme mit Umlauten :( } elsif ($answer{state} eq 'stop') { if ($reqinfo ne 't') { # muss ja nicht in allen Zeilen des LCD # der gleiche Fehler stehen print fstrtolen('Player gestoppt', $lcdlength, $align); } else { print fsomespaces($lcdlength); } } else { # vielleicht gibt's auch nur 'play', 'pause' und 'stop' als Status # aber sicher ist sicher if ($reqinfo ne 't') { print fstrtolen('Unbekannter Status des Players', $lcdlength, $align); } else { print fsomespaces($lcdlength); } } } else { # wenn connection zum mpd nicht erfolgreich if ($reqinfo ne 't') { print fstrtolen('MPD nicht erreichbar', $lcdlength, $align); } else { print fsomespaces($lcdlength); } }