Album

 view release on metacpan or  search on metacpan

script/album  view on Meta::CPAN

#!/usr/bin/perl -w
my $RCS_Id = '$Id: album.pl,v 1.86 2007/04/02 09:07:50 jv Exp $ ';

# Author          : Johan Vromans
# Created On      : Tue Sep 15 15:59:04 2002
# Last Modified By: Johan Vromans
# Last Modified On: Mon Apr  2 11:07:05 2007
# Update Count    : 2830
# Status          : Unknown, Use with caution!

################ Common stuff ################

$VERSION = "1.06";

use strict;

# Package or program libraries, if appropriate.
# $LIBDIR = $ENV{'LIBDIR'} || '/usr/local/lib/sample';
# use lib qw($LIBDIR);
# require 'common.pl';

# Package name.
my $my_package = 'Sciurix';
# Program name and version.
my ($my_name, $my_version) = $RCS_Id =~ /: (.+).pl,v ([\d.]+)/;
# Tack '*' if it is not checked in into RCS.
$my_version .= '*' if length('$Locker:  $ ') > 12;

my $creator = "Created with <a href=\"http://search.cpan.org/~jv/Album/\">Album</a> $::VERSION";

################ Command line parameters ################

use Getopt::Long 2.13;

# Command line options.
my $import_exif = 0;
my $import_dir;
my $update = 0;			# add new from large/import
my $dest_dir = ".";
my $info_file;
my $linkthem = 1;		# link orig to large, if possible
my $clobber = 0;
my $mediumonly = 0;		# only medium size (for web export)
my $externalize_formats = 0;	# create external format files
my $verbose = 1;		# verbose processing

# These are left undefined, for set_defaults. Note: our, not my.
our $index_columns;
our $index_rows;
our $thumb;
our $medium;			# medium size, between large and small
our $album_title;
our $caption;
our $datefmt;
our $icon;
our $locale;
our $lib_common;

# These are not command line options.
my $journal;			# create journal

# Development options (not shown with -help).
my $debug = 0;			# debugging
my $trace = 0;			# trace (show process)
my $test = 0;			# test mode.

# Process command line options.
app_options();

# Post-processing.
$trace |= ($debug || $test);
$dest_dir =~ s;^\./;;;
$import_dir =~ s;^\./;; if $import_dir;

################ Presets ################

use constant DEFAULTS => { info       => "info.dat",
			   title      => "Photo Album",
			   medium     => 0,
			   mediumsize => 915,
			   thumbsize  => 200,
			   indexrows  => 3,
			   indexcols  => 4,
			   caption    => "fct",
			   captionmin => "f",
			   dateformat => '%F',
			   icon	      => 0,
			 };

my $TMPDIR = $ENV{TMPDIR} || $ENV{TEMP} || '/usr/tmp';

my $picpat = qr{(?i:jpe?g|png|gif)};
my $movpat = qr{(?i:mpe?g|mov|avi)};
my $xtrpat = qw{(?i:html?)};
my $suffixpat = qr{\.$picpat|$movpat};
my $xsuffixpat = qr{\.$picpat|$movpat|$xtrpat};

my %capfun = ('c' => \&c_caption,
	      'f' => \&f_caption,
	      's' => \&s_caption,
	      't' => \&t_caption,
	     );

my $br = br();

# Max.number of clickable index numbers (should be odd).
use constant IXLIST => 15;

# Helper programs
my $prog_jpegtran  = findexec("jpegtran");
my $prog_mplayer   = findexec("mplayer");
my $prog_mencoder  = findexec("mencoder");

################ The Process ################

use File::Spec;
use File::Path;
use File::Basename;
use Time::Local;
use Image::Info;
use Image::Magick;
use Data::Dumper;
use POSIX qw(locale_h strftime);
use locale;

# The files already there, if any.
my $gotlist = new FileList;
# The files in the import dir, if any.
my $implist = new FileList;

# The list of files, in the order to be processed.
# This list is initialy filled from info.dat, and (optionally) updated
# from the other lists.
my $filelist = new FileList;

# This is the list of all entries to be journalled (all images, plus
# possible interspersed loose annotations).
my @journal;

# Load cached info, if possible.
load_cache();

# Load image names and info from the info file, if any.
# This produces the initial file list.
load_info();
#print STDERR Data::Dumper->Dump([$filelist],[qw(filelist)]);

# Load image names and info for files we already got.
load_files()  if -d d_large();
#print STDERR Data::Dumper->Dump([$gotlist],[qw(gotlist)]);

# Load image names and info for files we can import.
load_import() if $import_dir && -d $import_dir;
#print STDERR Data::Dumper->Dump([$implist],[qw(implist)]);

# Apply defaults to unset parameters.
set_defaults();

# warn("date => ", strftime($datefmt, localtime(time)), "\n");

# Verify and update the file list.
my $added = update_filelist();
#print STDERR Data::Dumper->Dump([$filelist],[qw(filelist)]);

my $num_entries = $filelist->tally;
print STDERR ("Number of entries = $num_entries",
	      $added ? " ($added added)" : "",
	      "\n") if $verbose > 1;
die("Nothing to do?\n") unless $num_entries > 0;
exit(0) if $test;

# Clean up and create directories.
if ( $clobber ) {
    rmtree([d_thumbnails(), d_medium()], $verbose > 1);
}
mkpath([d_large(), d_thumbnails(), d_icons(), d_css()], $verbose > 1);
mkpath([d_medium()], $verbose > 1) if $medium;

# Copy the button images over to the target directory.
add_button_images();

# Create the default style sheets, if necessary.
add_stylesheets();

script/album  view on Meta::CPAN

my @subdirs;

# Journal tags
my %jnltags;

# Note: the HTML generators use the file names relatively.
sub fjoin	 { File::Spec->catfile(@_); }
sub d_dest       { unshift(@_, $dest_dir) unless $dest_dir eq ".";
		   fjoin(@_); }
sub d_large      { unshift(@_, "large");      goto &d_dest; }
sub d_medium     { unshift(@_, "medium");     goto &d_dest; }
sub d_thumbnails { unshift(@_, "thumbnails"); goto &d_dest; }
sub d_journal    { unshift(@_, "journal");    goto &d_dest; }

sub d_destc      { unshift(@_, $lib_common) if $lib_common ne ""; goto &d_dest; }
sub d_icons      { unshift(@_, "icons");   goto &d_destc; }
sub d_css        { unshift(@_, "css");     goto &d_destc; }
sub d_fmt        { unshift(@_, "formats"); goto &d_destc;}

my %optcfg;			# option set from config files

sub setopt {
    no strict qw(refs);
    return if defined(${$_[0]});
    print STDERR ("setopt $_[0] -> $_[1]\n") if $trace;
    ${$_[0]} = $_[1];
    $optcfg{$_[0]} = 1;
}

sub parse_line {
    local ($_) = (@_);
    my $err = 0;

    if ( /^!?\s*(\S.*)/ ) {
	$_ = $1;
	if ( /^title\s+(.*)/ ) {
	    setopt("album_title", $1);
	}
	elsif ( /^page\s+(\d+)x(\d+)/ ) {
	    setopt("index_rows", $1);
	    setopt("index_columns", $2);
	}
	elsif ( /^thumbsize\s*(\d+)/ ) {
	    setopt("thumb", $1);
	}
	elsif ( /^mediumsize\s*(\d+)/ ) {
	    setopt("medium", $1);
	}
	elsif ( /^medium\s*(-?\d+)?/ ) {
	    setopt("medium", $1 || DEFAULTS->{mediumsize});
	}
	elsif ( /^dateformat\s*(.*)/ ) {
	    setopt("datefmt", $1);
	}
	elsif ( /^caption\s*(.*)/ ) {
	    setopt("caption", $1);
	}
	elsif ( /^icon\s*(.*)/ ) {
	    setopt("icon", defined($1) && length($1) ? $1 : 1);
	}
	elsif ( /^locale\s*(.*)/ ) {
	    setopt("locale", $1);
	}
	elsif ( /^depth\s+(\d+)/ ) {
	    # lib_common is used in the HTML, don't use fjoin.
	    setopt("lib_common", join("/", ("..") x $1));
	}
	else {
	    warn("Unknown control: $_[0]\n");
	    $err++;
	}
    }
    else {
	warn("Invalid control: $_[0]\n");
	$err++;
    }
    $err;
}

sub set_defaults {
    # Load settings from user files.
    my $sl;
    unless ( $sl = $ENV{ALBUMCONFIG} ) {
	$sl = ".albumrc";
	$sl .= ":".$ENV{HOME}."/.albumrc" if $ENV{HOME};
    }
    foreach my $cf ( split(/:/, $sl) ) {
	unless ( -f $cf ) {
	    warn("$cf: $!\n") if $ENV{ALBUMCONFIG};
	    next;
	}
	open(my $fh, "<$cf") || next;
	warn("parsing: $cf\n") if $trace;
	my $err = 0;
	while ( <$fh> ) {
	    next if /^\s*#/;
	    next unless /\S/;
	    $err += parse_line($_);
	}
	close($fh);
	die("Errors in config file $cf, aborted\n") if $err;
    }

    # Finally, apply defaults if necessary.
    warn("apply defaults\n") if $trace;
    setopt("album_title",   DEFAULTS->{title});
    setopt("index_rows",    DEFAULTS->{indexrows});
    setopt("index_columns", DEFAULTS->{indexcols});
    setopt("thumb",         DEFAULTS->{thumbsize});
    setopt("datefmt",       DEFAULTS->{dateformat});
    setopt("icon",          DEFAULTS->{icon});

    $medium = DEFAULTS->{mediumsize} if defined($medium) && !$medium || $mediumonly;
    $medium = 0 if defined($medium) && $medium < 0;

    # Caption values.
    setopt("caption", DEFAULTS->{( -s $info_file || $import_dir) ?
				 "caption" : "captionmin" });
    die("Invalid value for caption: $caption\n")
      unless $caption =~ /^[fsct]*$/i;
    $caption = lc($caption);

    if ( $locale ) {
	setlocale(LC_TIME, $locale);
	setlocale(LC_COLLATE, $locale);
    }

    if ( defined($lib_common) ) {
	$lib_common =~ s;/+$;;;
    }
    $lib_common ||= "";
}

sub load_info {
    my %typemap = ( 'p' => T_JPG, 'm' => T_MPG, 'v' => T_VOICE );

    # If an info has been supplied, it'd better exist.
    if ( $info_file ) {
	die("$info_file: $!\n") unless -s $info_file;
    }
    else {
	# Try default.
	$info_file = d_dest(DEFAULTS->{info});
	unless ( -s $info_file ) {
	    my $add_new; $add_new++ if $import_dir;
	    my $add_src; $add_src++ if -d d_large();
	    print STDERR ("No ", DEFAULTS->{info});
	    print STDERR (", adding images from ") if $add_src || $add_new;
	    print STDERR (d_large())               if $add_src;
	    print STDERR (" and ")                 if $add_src && $add_new;
	    print STDERR ($import_dir)             if $add_new;
	    print STDERR ("\n");
	    return;
	}
    }

    my $err = 0;
    my $file;
    my $tag;

    my $fh = do { local *FH; *FH };
    die("$info_file: $!\n")
      unless open($fh, $info_file);
    warn("parsing: $info_file\n") if $trace;

    my $el;
    my %dirs;

    while ( <$fh> ) {
	chomp;

	next if /^\s*#/;
	next unless /\S/;

	if ( /^\s+/ && $el ) {
	    $el->description($el->description . "\n" . $_);
	    next;
	}

	if ( /^!\s*(\S.*)/ ) {
	    $_ = $1;
	    if ( /^tag\s*(.*)/ ) {
		$tag = $1;
		$tag =~ s/\s$//;
		$tag =~ s/\s+/ /g;



( run in 0.639 second using v1.01-cache-2.11-cpan-ceb78f64989 )