#!/usr/bin/perl #Copyright (c) 2008, Zane C. Bowers #All rights reserved. # #Redistribution and use in source and binary forms, with or without modification, #are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED #WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. #IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, #INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, #DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF #LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR #OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. use strict; use warnings; use Getopt::Std; use Image::Size::FillFullSelect;; use ZConf; $Getopt::Std::STANDARD_HELP_VERSION=1; #version function sub main::VERSION_MESSAGE { print "zbgset 3.0.0\n"; }; #print help sub main::HELP_MESSAGE { print "\n". "-r choose a random background\n". "-f choose a set the bg as\n". "-l use the last BG\n". "\n". "-F fill type to use\n". "-s What set to use.\n". "\n". "FILL TYPES\n". "center\n". "tile\n". "full\n". "fill\n"; }; #process sub lastprocess{ my $last=$_[0]; my $file=$_[1]; my $filltype=$_[2]; my $numberoflast=$_[3]; #gets the hostname my $hostname=`hostname`; if(!defined($hostname)){ $hostname="localhost"; }else{ chomp($hostname); }; #creates the fist line of the new last my $newlast=$hostname.$ENV{DISPLAY}.":".$filltype.":".$file."\n"; my @lastA=split(/\n/, $last); my $lastInt=0; while(defined($lastA[$lastInt])){ if($lastInt <= $numberoflast){ $newlast=$newlast.$lastA[$lastInt]."\n"; }; $lastInt++; }; return $newlast; }; ## ##find everything in the path ## sub findInPath{ my $path=$_[0]; my $command='find \''.$path.'\' -type f'; my @files=`$command`; return @files; } #gets the options my %opts=(); getopts('F:f:lrs:', \%opts); my %args; #if -F is used, make sure it is a legit value if(defined($opts{F})){ my @filltypes=("auto", "center", "fill", "full", "tile"); #holds the various support fill types my $filltypesInt=0;#used for intering through @filltypes my $found=undef;#set to true when found while(defined($filltypes[$filltypesInt])){ #checks for a match if($opts{F} eq $filltypes[$filltypesInt]){ $found=1; }; $filltypesInt++; }; #exits if it is not supported if(!$found){ warn("zbgset:6: '".$opts{F}."' is not a support fill type."); exit 6; }; }; #makes sure the file exists if -f is used. if(defined($opts{f})){ if(!-f $opts{f}){ warn("zbgset:5: '".$opts{f}."' does not exist or is not a file."); exit 5; }; }; #inits zconf my $zconf = ZConf->new(); if($zconf->{error}){ warn("zbgset:1: Could not initiate ZConf. It failed with '".$zconf->{error}."'". ", '".$zconf->{errorString}."'."); exit 1; } #handles set checking if(defined($opts{s})){ if(!$zconf->setNameLegit($opts{s})){ warn("zbgset:4: '".$opts{s}."' is not a legit ZConf set name."); exit 11; }else{ $args{set}=$opts{s}; }; }else{ $args{set}=undef; }; #create the config if it does not exist #if it does exist, make sure the set we are using exists my $returned = $zconf->configExists("zbgset"); if(!$returned){ warn("zbgset: Has not been run before. Initiating config."); $returned = $zconf->createConfig("zbgset"); if($zconf->{error}){ warn("zbgset:2: Could not create config."); exit 2; }; #inits it my $returned=$zconf->writeSetFromHash({config=>"zbgset", set=>$args{set}}, { savelast=>"true", filltype=>"auto", numberoflast=>"15", postSetRefresh=>"false", postSetRefresher=>"zbgfbmb -l", maxdiff=>".2", filltype=>"auto", full=>'hsetroot -full \'%%%THEFILE%%%\'', tile=>'hsetroot -tile \'%%%THEFILE%%%\'', fill=>'hsetroot -fill \'%%%THEFILE%%%\'', center=>'hsetroot -center \'%%%THEFILE%%%\'', path=>'default' } ); warn("zbgset: Initilization succeeded."); }else{ #gets the set name if it is not defined if(!defined($args{set})){ $args{set}=$zconf->chooseSet("zbgset"); }; #gets the list of sets my @sets=$zconf->getAvailableSets("zbgset"); if($zconf->{error}){ warn("zbgset:3: Could not get a list of sets."); exit 3; }; #creates the default config if it the specified set has not been created before my $setsInt=0; #used for intering through @sets my $found=undef; while(defined($sets[$setsInt])){ #sets $found to true if the set is found if($sets[$setsInt] eq $args{set}){ $found=1; }; $setsInt++; }; #if found is false, initialize the set if(!$found){ warn("zbgset: The specified or auto choosen set, '".$args{set}. "' has not been initialized before. Doing so now."); #inits it my $returned=$zconf->writeSetFromHash({config=>"zbgset", set=>$args{set}}, { savelast=>"1", filltype=>"auto", numberoflast=>"15", postSetRefresh=>"0", postSetRefresher=>"zbgfbmb -l", maxdiff=>".2", filltype=>"auto", full=>'hsetroot -full \'%%%THEFILE%%%\'', tile=>'hsetroot -tile \'%%%THEFILE%%%\'', fill=>'hsetroot -fill \'%%%THEFILE%%%\'', center=>'hsetroot -center \'%%%THEFILE%%%\'', path=>'default', override=>'default', last=>'' } ); warn("zbgset: Initilization succeeded for set '".$args{set}."'."); }; }; $returned = $zconf->read({config=>"zbgset", set=>$args{set}}); if($zconf->{error}){ warn("zbgset:3: Could not read config. It failed with '".$zconf->{error}."'". ", '".$zconf->{errorString}."'."); exit 3; }; #sets up the setter to be used if(defined($opts{F})){ $args{filltype}=$opts{F}; }else{ $args{filltype}=$zconf->{conf}{zbgset}{filltype}; }; #handles it if -f is specified if(defined($opts{f})){ if($args{filltype} eq "auto"){ my $iffs = Image::Size::FillFullSelect->new(); $args{filltype} = $iffs->select($opts{f}); if(!defined($args{filltype})){ warn("zbgset:7: Auto selection for the image size failed. Image::Size". "does not regard the file, '".$opts{f}."', as a image."); exit 7; }; }; #get the setter to use and replace %%%THEFILE%%% with the file name. my $setter=$zconf->{conf}{zbgset}{$args{filltype}}; $setter=~s/%%%THEFILE%%%/$opts{f}/; system($setter); if($? ne "0"){ warn("zbgset:8: Setter, '".$setter."', failed with ".$?."."); exit 8; }; #makes sure last is a defined variable if(!defined($zconf->{conf}{zbgset}{last})){ $zconf->setVar("zbgset", "last", ""); }; $zconf->{conf}{zbgset}{last}=lastprocess($zconf->{conf}{zbgset}{last}, $opts{f}, $args{filltype}, $zconf->{conf}{zbgset}{numberoflast}); #saves the last $returned=$zconf->writeSetFromLoadedConfig({config=>"zbgset"}); if($zconf->{error}){ warn("zbgset:9: Could not save last information. It failed with '".$zconf->{error}."'". ", '".$zconf->{errorString}."'."); exit 9; }; exit 0; }; #sets the last background if(defined($opts{l})){ my @lastA=split(/\n/, $zconf->{conf}{zbgset}{last}); my @lastsplit=split(/:/, $lastA[0]); #get the setter to use and replace %%%THEFILE%%% with the file name. my $setter=$zconf->{conf}{zbgset}{$lastsplit[2]}; $setter=~s/%%%THEFILE%%%/$lastsplit[3]/; system($setter); if($? ne "0"){ warn("zbgset:8: Setter, '".$setter."', failed with ".$?."."); exit 8; }; exit 0; }; #handles if if a random background is selected if(defined($opts{r})){ if(defined($opts{p})){ $args{path}=$opts{p}; }else{ $args{path}=$zconf->{conf}{zbgset}{path}; }; my %paths=$zconf->regexVarGet("zbgset", "^paths/"); if(!defined($paths{"paths/".$args{path}})){ warn("zbgset:10: The requested path, '".$args{path}."' is not defined"); }; my @pathsA=split(/\n/ ,$paths{"paths/".$args{path}}); #gets which path to use my $randomPathInt=rand($#pathsA); $randomPathInt =~ s/\.[0123456789]*//; my @files=findInPath($pathsA[$randomPathInt]); my $randomFilesInt=rand($#files); $randomFilesInt =~ s/\.[0123456789]*//; #removes any \n at the end of the line chomp($files[$randomFilesInt]); if($args{filltype} eq "auto"){ my $iffs = Image::Size::FillFullSelect->new(); $args{filltype} = $iffs->select($files[$randomFilesInt]); if(!defined($args{filltype})){ warn("zbgset:7: Auto selection for the image size failed. Image::Size". "does not regard the file, '".$files[$randomFilesInt]."', as a image"); exit 7; }; }; #get the setter to use and replace %%%THEFILE%%% with the file name. my $setter=$zconf->{conf}{zbgset}{$args{filltype}}; $setter=~s/%%%THEFILE%%%/$files[$randomFilesInt]/; system($setter); if($? ne "0"){ warn("zbgset:8: Setter, '".$setter."', failed with ".$?."."); exit 8; }; #saves it $zconf->{conf}{zbgset}{last}=lastprocess($zconf->{conf}{zbgset}{last}, $files[$randomFilesInt], $args{filltype}, $zconf->{conf}{zbgset}{numberoflast}); #saves the last $returned=$zconf->writeSetFromLoadedConfig({config=>"zbgset"}); if($zconf->{error}){ warn("zbgset:9: Could not save last information. It failed with '".$zconf->{error}."'". ", '".$zconf->{errorString}."'."); exit 9; }; exit 0; }; exit 1; =head1 NAME zbgset - A perl program for managing the background. =head1 SYNOPSIS zbgset (B<-f> |B<-r>|B<-l>) [B<-F> ] [B<-s> ] =head1 USAGE Either -f, -r, or -l need used. This does not actually set the background, but calls another program to do it, but what makes it useful is it allows for random images to be used as well as the last image to be called. This makes it useful for setting the image upon login or changing it regullarly through cron. When it is ran for the first time it creates a ZConf config named "zbgset" used store the settings. =head1 ARGUEMENTS =head2 B<-f> This specifies a file to use. =head2 B<-F> This specifies the fill type to use. =head2 B<-l> Use the last image. =head2 B<-s> This is the ZConf set to use for it. If the set has not been initiated before it will do so. =head1 ZConf Keys =head2 center This contains the setter that will be used for when setting a centered image. '%%%THEFILE%%%' is replaced at runtime with the name of the file. center=hsetroot -center '%%%THEFILE%%%' =head2 fill This key contains setter to be used for fill the background with a resized image. '%%%THEFILE%%%' is replaced at runtime with the name of the file. fill=hsetroot -fill '%%%THEFILE%%%' =head2 full This key contains setter to be used for fill the background with a scaled image. '%%%THEFILE%%%' is replaced at runtime with the name of the file. full=hsetroot -full '%%%THEFILE%%%' =head2 last This contains the last several images set. There is one entry per line. The format is as below. ::: =head2 maxdiff This contains the maximum difference for between any two any two sides when choosing between fill and full. maxdiff=.2 =head2 numberoflast The number of last entries to save. =head2 path This is the path to use for when selecting a random image. =head2 paths/ This is a path. Each path have multiple paths. Each path is seperated by a new line. =head2 postSetRefresh Wether or not it should run something after it has been set. This is a perl boolean value. postSetRefresh=0 =head2 postSetRefresher If 'postSetRefresh' is set to true, this is ran. =head2 tile This key contains setter to be used for tiling. '%%%THEFILE%%%' is replaced at runtime with the name of the file. tile=hsetroot -tile '%%%THEFILE%%%' =head1 ERROR CODES =head2 1 Could not initial ZConf. =head2 2 Could not create config. =head2 3 Could not get set information. =head2 4 -f and -r switches both used when calling program. =head2 5 The specified file does not exist or is not a file. =head2 6 The specified fill type is not supported. =head2 7 Auto selection for the image size failed. Image::Size does not regard the file as a image. =head1 8 Execution of the setter failed. =head1 9 Saving the last information failed. =head1 10 Requested path is not defined. =head2 11 The set name you specified with '-s' is not a legit name for a ZConf set. =head1 AUTHOR Copyright (c) 2006, Zame C. Bowers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS` OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =head1 SCRIPT CATEGORIES Desktop =head1 OSNAMES any =head1 README zbgset - A perl program for managing the background. =cut