Here is what I hope is the final version. It corrects the incorrect folder sheet bug and is also a fair amount faster. The incorrect
folder sheet bug was caused by the fact that every sheet would get linked in as the folder sheet, you'd only get the correct result
if the proper folder sheet was the very last one processed. The bug is fixed by holding back all the in-exact name matches in a
list and only create them if nothing else created the link... so now it doesn't matter what order things were created in you get a
deterministic result given well formed input... this provides a speed win because spurious links are not being created/destroyed.
I also skipped creation of sheets for folders whose names start with a '.' because those are hidden anyway, they don't need sheets.
Cheers
Chris
- Code: Select all
#!/usr/bin/perl
### Copyright 2012 b-rad.cc
### http://wdlxtv.com & http://b-rad.cc & http://nextdimension.cc
### GPLv3 - full license located @ /usr/share/LICENSE
### Stipulations:
### - the full copyright notices in /osd/setup_about.xml must be left intact, as it is the publicly displayed copyright portion of this software as dictated by the GPLv3
### - this entire header must be left intact
## linksheets <location> <mode> [/msheets]
## recursively searches and symlinks movie sheets into /msheets
## /msheets is joined with /osd via unionfs
## -- if <mode> is 1 or 2 then max-levels=<mode>
## if [/msheets] is provided then that's where the links are created (for testing)
##
## valid types
## video thumb view:
## audio thumb view:
## list mode:
## - STD
## - SHEET
## - WALL
##
use strict;
use File::Basename;
use Cwd 'realpath';
# utility function for controlling the led
sub set_power_led{
my $mode = shift;
open(my $fh, ">>", "/proc/led");
print $fh "power led $mode\n";
close($fh);
}
# test to see if a string starts with a '.'
sub starts_with_dot{
$_ = shift;
if ( /^\./ ) {
return 1;
}
return 0;
}
if ( ! -e $ARGV[0] ) {
print ("PATH: " . $ARGV[0] . " does not exist!\n");
system("logger -t linksheets \"$ARGV[0] not found, exiting immediately!!!\"");
exit 2
}
my $MODE = $ARGV[1];
if ( -e '/tmp/STOP_DMARENDER' ) {
print "stop\n";
system("logger -t linksheets \"/tmp/STOP_DMARENDER exists, exiting immediately!!!\"");
exit 55
}
# parse config file into environment (so that it augments env)
open(my $fh, "<", "/conf/config");
while (!eof($fh)) {
my $inline = readline($fh);
if ($inline =~ /LISTNUM/ ||
$inline =~ /GENTHUMBS/ ||
$inline =~ /THUMBRESO/ ||
$inline =~ /MSHEET/ ||
$inline =~ /DEFAULTSHEET/) {
chomp($inline);
(my $var, my $val) = split("=", $inline);
$val =~ s/'//g;
#print ($var . "=" . $val . "\n");
$ENV{$var} = $val
}
}
close($fh);
# now extract the parameters from the augmented environment
my $MSHEETMODE = $ENV{'MSHEETMODE'};
my $GENMSHEET = $ENV{'GENMSHEET'};
my $VIDMSHEET = $ENV{'VIDMSHEET'};
my $LISTMSHEET = $ENV{'LISTMSHEET'};
my $DEFAULTSHEET = $ENV{'DEFAULTSHEET'};
my $LDEBUG = $ENV{'LDEBUG'};
# check that MSHEETMODE is legal
if ( $MSHEETMODE ne "wall" && $MSHEETMODE ne "sheet" && $MSHEETMODE ne "std" ) {
print "illegal MSHEETMODE\n";
system("logger -t linksheets \"illegal MSHEETMODE $MSHEETMODE, exiting immediately!!!\"");
exit 3;
}
# check that one of the sheet modes is active
if ( $GENMSHEET ne "ON" && $VIDMSHEET ne "ON" && $LISTMSHEET ne "ON" && $MODE ne "5" ) {
print "no generation mode selected\n";
system("logger -t linksheets \"no generation mode selected, exiting immediately!!!\"");
exit 3;
}
# configure the per-mode sheet pattern
my $SEARCHSTRING = ".*_sheet.$MSHEETMODE.jpg";
# setup the 'find' argument that will control the depth of it's recursive search
my $DEPTH = "";
if ( $MODE eq "1" || $MODE eq "2" ) {
$DEPTH = "-maxdepth " . $MODE;
}
system("logger -t linksheets \"Generating MovieSheets for " . $ARGV[0] . ", mode " . $ARGV[1] . "\"");
set_power_led('blink on');
if ( $DEFAULTSHEET ne "" && ! -l "/tmp/defaultsheet.jpg" ) {
# if the valut of DEFAULTSHEET starts with a / then it's
# a full path and we want to use it exactly, otherwise
# assume it's a path relative to /osd/
$_ = $DEFAULTSHEET;
if ( /^\// ) {
symlink($DEFAULTSHEET, "/tmp/defaultsheet.jpg");
} else {
symlink("/osd/" . $DEFAULTSHEET, "/tmp/defaultsheet.jpg");
}
}
# for testing, allow setting of a location to generate the links
if ( $#ARGV == 2 ) {
chdir($ARGV[2]);
} else {
chdir("/msheets");
}
# keep track of things we'll only link as a last resort
my %soft_links;
# make sure the link replaces the thing it currently points to
sub force_symlink{
my $src = shift;
my $dst = shift;
my $dbg = shift;
if ( -e $dst ) {
my $curr = realpath($dst);
if ( $curr eq $src ) {
return;
}
if ( $LDEBUG ne "" ) {
# for the purposes of logging, don't mention it if the files
# have the same size, ie: assume the user's name space does
# this for a sane reason
(my $src_dev,my $src_ino,my $src_mode,my $src_nlink,
my $src_uid,my $src_gid,my $src_rdev,my $src_size,
my $src_atime,my $src_mtime,my $src_ctime,
my $src_blksize,my $src_blocks) = stat($src);
(my $curr_dev,my $curr_ino,my $curr_mode,my $curr_nlink,
my $curr_uid,my $curr_gid,my $curr_rdev,my $curr_size,
my $curr_atime,my $curr_mtime,my $curr_ctime,
my $curr_blksize,my $curr_blocks) = stat($curr);
if ($src_size == $curr_size) {
# assume it's the same image
} else {
print "change mind: " . $src . "\n";
print " : " . $curr . "\n";
print " : " . $dst . "\n";
}
}
unlink($dst);
}
symlink($src, $dst);
}
my $find_cmd = "find $ARGV[0]/ -type f $DEPTH ";
$find_cmd .= "-regextype posix-egrep ";
$find_cmd .= "-iregex \".*_sheet.jpg|.*wd_tv.jpg|" . $SEARCHSTRING . "\"";
open(my $fh, $find_cmd . " 2>/dev/null |");
while (!eof($fh)) {
my $msheet = readline($fh);
chomp($msheet);
my $basename_msheet = basename($msheet);
if ( $MSHEETMODE ne "std" && ($basename_msheet eq "wd_tv.jpg" ||
$basename_msheet eq ".wd_tv.jpg") ) {
# special handling for [.]wd_tv.jpg:
# just link it as it's folder name
my $DIRNAME = basename(dirname($msheet));
if ( ! starts_with_dot($DIRNAME) ) { # skip invisible dirs
force_symlink($msheet, $DIRNAME,"l1 ");
if ( $LDEBUG ne "" ) { print "l1 $msheet -> $DIRNAME\n"; }
}
} elsif ( $MSHEETMODE ne "std" && ($basename_msheet eq "folder.jpg_sheet.jpg" ||
$basename_msheet eq ".folder.jpg_sheet.jpg" ) ) {
# special handling for [.]folder.jpg_sheet.jpg
# just link it as it's folder name if there is no $MSHEETMODE.jpg form
# (as we intend to use that one in instead as the sheet for $DIRNAME)
my $NOEXT = substr($msheet,0,-4);
if ( ! -f "$NOEXT.$MSHEETMODE.jpg" ) {
my $DIRNAME = basename(dirname($msheet));
if ( ! starts_with_dot($DIRNAME) ) { # skip invisible dirs
force_symlink($msheet, $DIRNAME, "l2 ");
if ( $LDEBUG ne "" ) { print "l2 $msheet -> $DIRNAME\n"; }
}
}
} elsif ( substr($msheet,-10) eq "_sheet.jpg" ) {
# handle all images that end in _sheet.jpg
my $BASENAME = basename($msheet, "_sheet.jpg");
$BASENAME =~ s/^\.//; # remove leading '.' (if it exists)
my $NOEXT = substr($msheet, 0, -4);
my $DIRPATH = dirname($msheet);
my $DIRNAME = basename($DIRPATH);
if ( $MSHEETMODE eq "std" ) {
# it is not clear what this is trying to do or if it makes any sense
my $BASELINK = basename(realpath($DIRNAME));
if ( $BASELINK ne "" && substr($BASELINK,0,-10) ne $DIRNAME ) {
unlink($DIRNAME);
if ( $LDEBUG ne "" ) { print "ul3 $msheet -> $DIRNAME\n"; }
}
} else {
# link in as folder sheet if a more specialized form do not exist
if ( starts_with_dot($DIRNAME) ) {
# skip invisible dirs
} elsif ( ! -f "$NOEXT.$MSHEETMODE.jpg" &&
! -f "$DIRPATH/folder.jpg_sheet.jpg" &&
! -f "$DIRPATH/folder.jpg_sheet.$MSHEETMODE.jpg" ) {
if ( $BASENAME eq $DIRNAME ) {
# exact name match, do nothing, the 'l3a' link will pick it up
} elsif ( ! -e $DIRNAME ) {
# inexact name match, record that we'll make the link
# but don't do so until all other possible matches
# have been attempted
$soft_links{$DIRNAME} = $msheet;
}
}
}
# link in as file sheet if a more specialized form do not exist
if ( ! -f "$NOEXT.$MSHEETMODE.jpg" ) {
force_symlink($msheet, $BASENAME, "l3a");
if ( $LDEBUG ne "" ) { print "l3a $msheet -> $BASENAME\n"; }
}
} else {
# handle all other images
my $BASENAME = basename($msheet,"_sheet.$MSHEETMODE.jpg");
$BASENAME =~ s/^\.//g; # remove leading '.' (if it exists)
my $DIRPATH = dirname($msheet);
my $DIRNAME = basename($DIRPATH);
if ( $MSHEETMODE eq "std" ) {
# it is not clear what this is trying to do or if it makes any sense
my $BASELINK = basename(realpath($DIRNAME));
if ( $BASELINK ne "" && substr($BASELINK,0,-(11+length($MSHEETMODE))) ne $DIRNAME ) {
unlink($DIRNAME);
if ( $LDEBUG ne "" ) { print "ul4 $msheet -> $DIRNAME\n"; }
}
} else {
# link in as folder sheet if a more specialized form do not exist
if ( starts_with_dot($DIRNAME) ) {
# skip invisible dirs
} elsif ( ! -f "$DIRPATH/folder.jpg_sheet.jpg" &&
! -f "$DIRPATH/folder.jpg_sheet.$MSHEETMODE.jpg" ) {
if ( $BASENAME eq $DIRNAME ) {
# exact name match, do nothing, the 'l4a' link will pick it up
} elsif ( ! -e $DIRNAME ) {
# inexact name match, record that we'll make the link
# but don't do so until all other possible matches
# have been attempted
$soft_links{$DIRNAME} = $msheet;
}
}
}
# link in as file sheet
force_symlink($msheet, $BASENAME, "l4a");
if ( $LDEBUG ne "" ) { print "l4a $msheet -> $BASENAME\n"; }
}
# check to see if we've been asked to stop
if ( -f "/tmp/linksheets.stop.$MODE" ||
-f "/tmp/linksheets.stop" ) {
set_power_led('blink off');
set_power_led('on');
system("logger -t linksheets \"linksheets.stop found, exiting immediately!!!\"");
exit 3;
}
}
# now process any soft links, anything that gets
# logged indicates that the given folder does not
# have a properly named sheet
foreach my $DIRNAME (keys(%soft_links)) {
if ( ! -e $DIRNAME ) {
my $msheet = $soft_links{$DIRNAME};
symlink($msheet, $DIRNAME);
if ( $LDEBUG ne "" ) { print "l5 $msheet -> $DIRNAME\n"; }
}
}
set_power_led('blink off');
set_power_led('on');
system("logger -t linksheets \"Done MovieSheets for " . $ARGV[0] . ", mode " . $ARGV[1] . "\"");