#!/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 |B|B) [B ] [B ]
=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
This specifies a file to use.
=head2 B
This specifies the fill type to use.
=head2 B
Use the last image.
=head2 B
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