Screenshot of my new screensaver
The “challenge” I faced was to configure my screensaver to display randomly my favorite quotes, and this in my Linux KDE4 based environment.Unfortunately none of the screensavers shipped with KDE4 provides this option. I was ready to develop my own screensaver when I realized that the xscreensaver project provides several screensavers designed to display text coming from the output of a custom command. Xscreensaver has the great advantage of not being distribution dependant as it is shipped on most Linux and Unix systems running the X11 Window System. The good news also was that the Mandriva distribution I use provides an xcreensaver rpm that once installed integrates the different screensavers shipped with xcreensavers directly in the KDE4 list of screensavers so there is no need to manually modify the X11 configuration.
So the remaining problem was to create a custom command to print randomly one of my favorite quotes. I first defined a simple XML format to save my quotes. Below an example of an XML file that I named quotes.xml and in which I saved two quotes to illustrate the concept:
<?xml version="1.0" encoding="UTF-8"?> <collection> <quote id='orwell-01' category="literature" reference="George Orwell - Animal Farm - 1945"> Man is the only creature that consumes without producing. He does not give milk, he does not lay eggs, he is too weak to pull the plough, he cannot run fast enough to catch rabbits. Yet he is lord of all the animals. He sets them to work, he gives back to them the bare minimum that will prevent them from starving, and the rest he keeps for himself </quote> <quote id='shakespeare-01' category="literature" reference="William Shakespeare - Hamlet - ~1600"> To be, or not to be, that is the question: Whether 'tis nobler in the mind to suffer The slings and arrows of outrageous fortune, Or to take arms against a sea of troubles, And by opposing end them? To die, to sleep, No more; and by a sleep to say we end The heart-ache, and the thousand natural shocks That flesh is heir to: 'tis a consummation Devoutly to be wished. To die, to sleep; To sleep, perchance to dream – ay, there's the rub: For in that sleep of death what dreams may come, When we have shuffled off this mortal coil, Must give us pause – there's the respect That makes calamity of so long life. For who would bear the whips and scorns of time, The oppressor's wrong, the proud man's contumely, The pangs of disprized love, the law’s delay, The insolence of office, and the spurns That patient merit of the unworthy takes, When he himself might his quietus make With a bare bodkin? Who would fardels bear, To grunt and sweat under a weary life, But that the dread of something after death, The undiscovered country from whose bourn No traveller returns, puzzles the will, And makes us rather bear those ills we have Than fly to others that we know not of? Thus conscience does make cowards of us all, And thus the native hue of resolution Is sicklied o'er with the pale cast of thought, And enterprises of great pith and moment, With this regard their currents turn awry, And lose the name of action. Soft you now, The fair Ophelia! Nymph, in thy orisons Be all my sins remembered. </quote> </collection>
Then I created a simple PERL script named gl that parses this XML file (it requires for this purpose the excellent XML::Twig perl module usually shipped with the perl-XML-Twig rpm), chooses randomly one quote and prints it to the standard output :
#!/usr/bin/perl use strict; use utf8; use Encode qw(encode decode); use Getopt::Long; use XML::Twig; #PERL module usually shipped in the perl-XML-Twig rpms #---------------- BEGINNING OF CONFIGURABLE SECTION -----------------------------# my $xml_collection = '/home/kwartik/quotes.xml'; my $encoding='utf8'; #---------------- END OF CONFIGURABLE SECTION -----------------------------------# GetOptions( "c|collection=s" => \$xml_collection, "e|encoding=s" => \$encoding, ); if ( $xml_collection eq "" ) { print "SYNTAX : gl [-c|--collection path_to_xml_collection] [-e|--encoding encoding]\n\n" ."encoding option examples : 'utf8' 'iso-8859-1'\n"; exit 1; } (-f $xml_collection) or die ("Error: collection $xml_collection is not a file.\n"); my $nb_entries = 0; my %hash_collection = (); sub quote { my( $twig, $item )= @_; my $id = $item->att('id'); my $category = $item->att('category'); my $reference = $item->att('reference'); $hash_collection {$id} {'category'} = $category; $hash_collection {$id} {'reference'} = $reference; $hash_collection {$id} {'quote'} = $item->text; $twig->purge; $nb_entries ++; } my $twig= new XML::Twig( twig_handlers => { 'quote' => \"e } ); $twig->parsefile( $xml_collection ); sub print_quote( $ ) { my $entry = $_[0]; my $category = $hash_collection{$entry}{'category'}; my $quote = $hash_collection{$entry}{'quote'}; my $reference = $hash_collection{$entry}{'reference'}; printf("%s (%s)\n", encode($encoding, $quote) , encode($encoding, $reference) ); } my $choice = int(rand($nb_entries)); my @entry = ( sort {$a cmp $b} keys %hash_collection ); print_quote($entry[$choice]); exit 0; print "\n";
The final step is to link xscreensaver to gl. I first chose the Phosphor screensaver in the KDE4 screensaver list (accessible in “Configure your desktop/desktop/screensaver”).
Selection of Phosphor screensaver in the KDE4 screensaver list once the xscreensaver rpm has been installed
Then I used the screensaver-demo command to configure the Phosphor screensaver.
Configuration of the phosphor screensaver with the xscreensaver-demo command
The advanced tab allows to specify the custom command that xscreensaver must call to display text.
Configuration of the phosphor screensaver with the xscreensaver-demo command (advanced tab)
In the Program field, I have set the value sleep3;/usr/local/bin/gl -e iso-8859-1 to configure Phosphor to print every 3 seconds the output of gl. The -e iso-8859-1 option is used to make sure that gl prints the content in ISO-8859-1 (otherwise accents and other diacritics are badly displayed by Phosphor). It is important to notice in this example that both my XML collection file and gl script have been saved with in UTF-8. I could have also set sleep3;clear;/usr/local/bin/gl -e iso-8859-1 to ask xscreensaver to clear the screen between each quote. I have also discovered that the fortune command (usually shipped with the fortune-mod rpm) is a tool that provides many possibilities to randomly display quotes and it was indeed proposed by default by xscreensaver.