Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2006  »  08  »  Ich glotz' TV  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Listbox mit Index

Welcher Eintrag in der Listbox gerade selektiert ist, erkennt die Methode »get_active_id()« des Listbox-Objekts », die den Index des korrespondierenden Listenelements zurückgibt. Das Modul »Videodir.pm« (siehe weiter unten) hält sich eine Datenstruktur, die jedem Eintrag in der Listbox über seine ID die Metadaten seines Videos zuordnet.

Der zweite von der Listbox verarbeitete Event ist »-onchange«. Ihn löst der User aus, wenn er auf einem selektierten Eintrag die [Enter]-Taste betätigt oder mit der Maus auf einen Eintrag klickt. Das ist für »tv« das Signal, dass der User das Video ansehen will. Zeile 67 ruft den Mplayer mittels Backticks und »&« im Hintergrund auf. Das ist wichtig, denn das GUI muss weiter Tastatureingaben verarbeiten, sonst friert es ein.

Zusätzlich zu dieser Callback-Definition der Listbox legt Zeile 38 fest, dass das Betätigen von [Return] die Funktion »selected()« auslöst. Das Makro »KEY_ENTER()« ist im Modul »Curses« definiert und bezeichnet die [Return]- oder [Enter]-Taste. Dank des zuvor definierten Onchange-Eventhandlers der Listbox geschähe dies zwar auch ohne die explizite »set_binding«-Anweisung - denn jede Auswahl eines Listbox-Eintrags löst einen Onchange-Event aus. Doch scheiterte dies, sobald der User denselben Eintrag nochmals auswählt.

Die Zeilen 40 bis 42 belegen weitere Tasten. Des TV-Konsums Müde drücken [Q], und »tv« bricht mit »exit 0« ab. Die Taste [D] löscht über »delete_confirm()« ab Zeile 107 die selektierte Videodatei, ringt dem Benutzer aber zuvor per Dialog eine Bestätigung ab. Verleiht er einer Datei ein Sternchen (»*«), setzt das die Funktion »keep« in Gang, die in der Metadatenbank die Datei-TTL das Löschen verhindernd auf 1000 Tage setzt.

Die Methode »ttl_icon« ab Zeile 48 sorgt dafür, dass das GUI die Videos je nach TTL unterschiedlich darstellt. Ist sie kleiner als null, die Datei also zum Löschen freigegeben, erscheint ein Ausrufezeichen, bei einer TTL kleiner als fünf Tage gar nichts und sonst ein Sternchen. Nach all den Vorbereitungen ist das GUI nun vollständig aufgesetzt.

In Zeile 45 startet die »mainloop« des Moduls Curses::UI::POE, das den POE-Kernel mit dem damit verbundenen Multitasking-Reigen auslöst. Eine reine POE-Anwendung dürfte keine synchronen Plattenzugriffe ausführen. Dass »tv« hin und wieder rasch die Inode-Daten der Videodateien ausliest, geht aber gerade noch an. Das GUI kann so zwar etwas ruckeln, aber nie richtig einfrieren.

Ändert sich etwas im Videoverzeichnis, bekommt der »wake_up_handler()« das beim nächsten periodischen Aufruf, also spätestens nach 60 Sekunden über die in Zeile 91 aufgerufene Methode »rescan()« des Moduls »Videodir.pm« mit. Er frischt dann die innere Datenstruktur des Moduls auf. Diese Daten wandern dank der anschließend aufgerufenen Funktion »redraw()« ab Zeile 125 umgehend in die angezeigte Listbox. Deren »draw()«-Methode zeichnet die grafische Darstellung neu. Da sich eventuell auch die Anzahl der Dateien und deren Plattenplatzbedarf oder sogar der ausgewählte Eintrag ändert, zeichnet »redraw()« die Kopf- und Fußbalken auch gleich neu.


Abbildung 3: Der Dialog zum Löschen einer Sendung erscheint nach dem Drücken der Taste [D] und nötigt dem Benutzer eine Bestätigung seines Ansinnens ab.

Videoten aller Länder

Das Modul »Videodir.pm« in Listing 2 abstrahiert den Zugriff auf die Videodateien. Das auf »~/tv« eingestellte Verzeichnis enthält nicht nur alle Videofiles, sondern auch eine Datei ».meta«, die deren Verfallsdaten im YAML-Format speichert (Abbildung 4). Unter dem Schlüssel »keep« steht in ».meta«, wie viele volle Tage eine Datei nach ihrer Landung im Verzeichnis erhalten bleibt.

Listing 2:
»Videodir.pm«

001 ###########################################
002 package Videodir;
003 ###########################################
004 use strict; use warnings;
005 use YAML qw(LoadFile DumpFile);
006 use File::Basename;
007 
008 ###########################################
009 sub new {
010 ###########################################
011   my($class, %options) = @_;
012 
013   my $self = {
014     dir          => "$ENV{HOME}/tv",
015     meta_file    => ".meta",
016     keep_default => 5,
017     meta         => {},
018     max_gigs     => 20,
019     %options };
020 
021   $self->{meta_path} =
022      "$self->{dir}/$self->{meta_file}";
023 
024   bless $self, $class;
025   $self->rescan();
026   return $self;
027 }
028 
029 ###########################################
030 sub rescan {
031 ###########################################
032   my($self) = @_;
033   if(-f $self->{meta_path}) {
034     $self->{meta} =
035         LoadFile($self->{meta_path});
036   }
037 
038   $self->{total_size} = 0;
039   my @items = ();
040 
041   my $dir = $self->{dir};
042   for my $path (<$dir/*>) {
043 
044     next unless -f $path;
045     my $file = basename $path;
046 
047     $self->{meta}->{$file}->{keep} =
048        $self->{keep_default} unless defined
049        $self->{meta}->{$file}->{keep};
050 
051     my $size = -s $path;
052     $self->{total_size} += $size;
053 
054     my $age  = age_in_days($path);
055 
056     push @items, {
057       file => $file,
058       path => $path,
059       age  => $age,
060       size => gb($size),
061       ttl  =>
062           $self->{meta}->{$file}->{keep} -
063           $age,
064     };
065   }
066 
067   $self->{total_size} =
068       gb($self->{total_size});
069 
070     # Delete outdated entries
071   for my $k (keys %{$self->{meta}}) {
072      delete $self->{meta}->{$k} unless
073          -f "$self->{dir}/$k";
074   }
075 
076   $self->meta_save();
077 
078     # Sort by descending by age
079   $self->{items} = [
080     sort { $a->{age} <=> $b->{age} }
081          @items ];
082   return $self->{items};
083 }
084 
085 ###########################################
086 sub gb {           # Umrechnen in Gigabytes
087 ###########################################
088   my($val) = @_;
089   return sprintf "%.1f", $val / (1024**3);
090 }
091 
092 ###########################################
093 sub remove {
094 ###########################################
095   my($self, $file) = @_;
096 
097   my $path = "$self->{dir}/$file";
098   if(-f $path) {
099     unlink $path or
100       die "Cannot unlink $path";
101   }
102   $self->rescan();
103 }
104 
105 ###########################################
106 sub age_in_days {
107 ###########################################
108     my($file) = @_;
109 
110     return(sprintf "%.1f", (time() -
111        (stat $file)[9]) / 24 / 3600);
112 }
113 
114 ###########################################
115 sub shrink {
116 ###########################################
117   my($self) = @_;
118 
119   my $deleted = 0;
120   my @doomed = reverse
121                grep { $_->{ttl} < 0 }
122                @{$self->{items}};
123   while($self->{total_size} >
124         $self->{max_gigs}) {
125     last unless @doomed;
126     my $item = shift @doomed;
127     $deleted++;
128     $self->remove($item->{file});
129   }
130   return $deleted;
131 }
132 
133 ###########################################
134 sub meta_save {
135 ###########################################
136   my($self) = @_;
137   DumpFile($self->{meta_path},
138            $self->{meta});
139 }
140 
141 1;


Abbildung 4: Die Metadaten in »~/tv/.meta« liegen im YAML-Format vor. Sie speichern das Verfallsdatum der Videodateien.

Das im Dateisystem gespeicherte Modifikationsdatum der Datei dient als Zeitstempel. Um die Time to live der Datei zu bestimmen, berechnet »Videodir.pm« in der Funktion »age_in_days« zunächst die Differenz der gegenwärtigen Zeit und der Unix-Mtime der Datei in Tagen. Die TTL ergibt sich dann aus der Differenz des in der Metadatei festgelegten »keep«-Werts (in Tagen) und dem Dateialter (Zeile 62). Der Konstruktor »new« definiert ab Zeile 13 einige Defaultwerte für Konstanten, die der Aufrufer aber überschreiben darf. Erzeugt er zum Beispiel ein Objekt mit »new(max_gigs => 50)«, ist die Speicherplatzobergrenze nicht mehr 20, sondern 50 GByte.

Die Methode »rescan« ab Zeile 30 durchwandert sowohl das Videoverzeichnis (mit dem Glob »/*«, das ».meta« nicht findet) als auch die Metadatei, die »rescan« mit der Funktion »LoadFile()« des YAML-Moduls einliest. Die Methode frischt die unter dem Schlüssel »items« gespeicherte interne Datenstruktur dem aktuellen Zustand entsprechend auf. Jedes Element im Array unter »items« ist eine Referenz auf einen Hash, der Werte zu diesen Schlüsseln enthält:

  • »file«: Dateiname
  • »path«: absoluter Pfad
  • »age«: Alter in Tagen
  • »size«: Dateigröße in GByte
  • »ttl«: Zeit in Tagen bis zum Aufheben des
    Löschschutzes

Neu entdeckte Dateien erhalten in der Metadatei automatisch einen »keep«-Wert von fünf Tagen (Parameter »keep_default«). Am Ende von »rescan« schreibt »Videodir.pm« die neuen »keep«-Werte mit »meta_save()« in die Metadatei zurück. Die Zeilen 71 bis 74 werfen zuvor Dateien aus der Metadatei, die seit dem letzten Scan von der Festplatte verschwunden sind.

Ist die Plattenplatzgrenze überschritten, löscht die Methode »shrink()« so lange freigegebene Dateien, bis das Videoverzeichnis sich wieder im Rahmen hält. Dabei filtert sie mit »grep« alle Einträge heraus, deren »ttl«-Eintrag kleiner null ist. Da die Einträge im Array unter »->{items}« absteigend nach dem Datum sortiert sind (neue kommen zuerst), dreht »reverse« diese Ergebnisliste um, um die Dateien in der Reihenfolge ihrer Fälligkeit zu sortieren. Ist die Obermarke noch nicht erreicht, kehrt »shrink()« tatenlos zurück und liefert den Wert 0. Dies nutzt die aufrufende Stelle im Skript »tv«, die die dargestellte Listbox nur auffrischen muss, falls tatsächlich Dateien verschwunden sind.

Sie können diesen Artikel als PDF für 99 Cent kaufen. Klicken Sie dazu einfach auf eine der beiden Bezahloptionen Paypal oder ClickandBuy.


Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Episodenfilm Perl-Skript steuert Videowiedergabe
Netz-Journal Perl-Skript für periodische Kommandoaufrufe
Am Fließband Automatisiert Zeitschriftenartikel in PDF-Files konvertieren
Heilig nach Punkten Messenger-Plugin verschafft Vorteil durch Webseiten-Überwachung
Projekteküche Aktueller Überblick über freie Software und ihre Macher
Kein Etikettenschwindel Perl-Skript katalogisiert Bücher und CDs dank Barcodes
Whitepaper
Usage Landscape Enterprise Open Source Data Integration

Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.

Download PDF (Registrierung erforderlich)
Daten Migration - Eine Publikation von Bloor Research

Datenmigrationsprojekte überschreiten häufig das Budget, neigen zu Verzögerung und werden unter Umständen komplett abgebrochen. Bloor Research ist eines der weltweit führenden IT-Forschungs-, Analyse- und Beratungsunternehmen und wird in dem vorliegenden White Paper die wichtigsten Aspekte dieser Problematik näher beleuchten. Ferner werden praktische Empfehlungen für erfolgreiche Migrationsprojekte gegeben, die Sie auf Ihr nächstes Projekt übertragen können.

Download PDF (Registrierung erforderlich)
Kommentare (0)