#!/usr/bin/perl

#######################################################################
# LiVES photo_still plugin v0.1

# rendered plugins should accept:
# <plugin_name> version (return <plugin_name> version <version>)
# <plugin_name> get_capabilities
# <plugin_name> get_description (e.g. "Edge detect|Edge detecting|1|1|")
# and optionally any of: 
# <plugin_name> get_parameters
# <plugin_name> get_param_window
# <plugin_name> get_onchange
# <plugin_name> onchange_<when> (for any triggers, e.g. onchange_init)
#
# they must accept:
# <plugin_name> process <parameters>

# You should not skip any frames, if a frame is not changed you must do:
# `cp $in $out`
#
# for *non-Perl* plugins, LiVES will call:
# <plugin_name> process "<dir>" <in_ext> <out_ext> <start> <end>
#  <width> <height> <parameters>
# first you should chdir to <dir>
# then you should create all output frames %8d$out_ext in numerical 
# from start to end inclusive,
# each time calling sig_progress (see smogrify) - writes current frame number to 
# <dir>/.status
# and checking for pause
#
# Any errors should be transmitted as in sig_error - 
# write "error|msg1|msg2|msg3|" to <dir>/.status
# msgn must not contain "\n", but can be omitted

# output frames should be named %8d$out_ext in the same directory
# after processing, you should leave no gaps in out frames, you should not resize
# or change the palette from RGB24 (LiVES will check and autocorrect this soon)

# Also you must implement your own: &sig_error and &sig_progress


#######################################################################

my $command=$ARGV[0];

if ($command eq "get_capabilities") {
    # capabilities is a bitmap field
    # 0x0001 == slow (hint to GUI)
    # 0x0002 == may resize (all frames to  x )
    # 0x8000 == reserved
    print "32768\n";
    exit 0;
}

if ($command eq "version") {
    print "photo_still version 0.2 : builder version 0.9.5\n";
    exit 0;
}

if ($command eq "get_description") {
    #format here is "Menu entry|Action description|min_frames|script_file_name|"
    # min_frames==-1 indicates a special "no processing" effect. This allows more
    #general parameter windows which are not really effects (e.g. frame_calculator)
    print "Photo/still|Photo/still|1|1||\n";
    exit 0;
}


if ($command eq "get_parameters") {
    # "name|group|type|default|min|max|"
    # eg. print "Radius|0|num0|1|1|100|";
    # types can be numx,colRGB24,bool,string or string_list
    print "_Flash for|0|num0|6|0|100|\n";
    print "_Hold for|0|num0|100|1|10000|\n";
    print "Flash _colour|0|colRGB24|255|255|255|\n";
    print "_Black and white camera|0|bool|1|\n";
    exit 0;
}

if ($command eq "get_param_window") {
    print "layout|p1|\"frames\"|fill||\n";
    print "layout|p3||\n";
    print "layout|p2|\"frames\"|fill||\n";
    exit 0;
}

if ($command eq "get_onchange") {
    print "init|\n";
    print "1|\n";
    exit 0;
}

#######################################################

if ($command eq "process") {

# in case of error, you should do:
# &sig_error("msg1","msg2","msg3","msg4"); [ msg's are optional, but must not
# contain newlines (\n) ]

    $livesexitcode=1;
    $SIG{'HUP'}="dopost";

##### check requirements first #######
    if (&location("convert") eq "") {
      &sig_error("You must install 'convert' before you can use this effect.");
    }

###### handle parameters #############
# autogenerated from get_parameters

    unless (defined($ARGV[1])) {
      $p1=6;
    }
    else {
      $p1=$ARGV[1];
    }
    unless (defined($ARGV[2])) {
      $p2=100;
    }
    else {
      $p2=$ARGV[2];
    }
    unless (defined($ARGV[3])) {
      $p3=255;
    }
    else {
      $p3=$ARGV[3];
    }
    unless (defined($ARGV[4])) {
      $p4=1;
    }
    else {
      $p4=$ARGV[4];
    }
    $p1=int($p1*1+.5)/1;
    if ($p1<0) {
       &sig_error("_Flash for must be >= 0");
    }
    if ($p1>100) {
       &sig_error("_Flash for must be <= 100");
    }
    $p2=int($p2*1+.5)/1;
    if ($p2<1) {
       &sig_error("_Hold for must be >= 1");
    }
    if ($p2>10000) {
       &sig_error("_Hold for must be <= 10000");
    }
    $p4=~(~$p4);
$p3=int($p3);
if ($p3>0xFFFFFF||$p3<0) {
    &sig_error("Invalid colour for Flash _colour.");
}
$p3_red=int($p3/65536);
$p3-=$p3_red*65536;
$p3_green=int($p3/256);
$p3-=$p3_green*256;
$p3_blue=$p3;

    #make flash frame
    $cstring=&RGB24_to_string($p3_red,$p3_green,$p3_blue);
    `$convert_command -size $width!x$height! xc:$cstring flash$img_ext`;
    
    $has_store=0;
    
    #bit of a cheat for faster finishing
    $end=$start+$p1+$p2-1;

################# loop through frames #################
    for ($frame=$start;$frame<=$end;$frame++) {
	# sig progress will update the progress bar from $start->$end
	&sig_progress($frame);
	$name=&mkname($frame);
	$in="$name$img_ext";
	$out="$name.mgk";

##################### the all-important bit #######################

        $i=$frame-$start;
        
        if ($p2&&!$has_store) {
        	$has_store=1;
        	if ($p4) {
        		system("$convert_command $in -modulate 100,0,100 store$img_ext");
        	}
        	else {
        		`cp $in store$img_ext`;
        	}
        }
        
        #################
        
        if ($i<$p1) {
         # replace frame with flash frame
        	`cp flash$img_ext $out`;
        }
        elsif ($i<$p1+$p2) {
        	# replace with stored frame
        	`cp store$img_ext $out`;
        }
        else {
        	`cp $in $out`;
        }

###################################################################
        if (! -f $out) {
            print "Warning: effect plugin photo_still skipped frame $frame !";
            `cp $in $out`;
        }
        if ($p3_red>255) {
            $p3_red=255;
        }
        elsif ($p3_red<0) {
            $p3_red=0;
        }
        if ($p3_green>255) {
            $p3_green=255;
        }
        elsif ($p3_green<0) {
            $p3_green=0;
        }
        if ($p3_blue>255) {
            $p3_blue=255;
        }
        elsif ($p3_blue<0) {
            $p3_blue=0;
        }
    }
    $livesexitcode=0;
    &dopost;
    return 1;
}



########## Post loop code ############
sub dopost {
    unlink <"store$img_ext" "flash$img_ext">;
     
    if ($livesexitcode) {
        exit $livesexitcode;
    }
}

########## Triggers ############

if ($command eq "onchange_1") {
    $p1=@ARGV[1];
    $p1_min=@ARGV[2];
    $p1_max=@ARGV[3];
    $p2=@ARGV[4];
    $p2_min=@ARGV[5];
    $p2_max=@ARGV[6];
    $p3_red=@ARGV[7];
    $p3_green=@ARGV[8];
    $p3_blue=@ARGV[9];
    $p4=@ARGV[10];
    $width=@ARGV[11];
    $height=@ARGV[12];
    $start=@ARGV[13];
    $end=@ARGV[14];
    $last=@ARGV[15];
    $length=$end-$start+1;

    $p2_max=$length-$p1;

    print "$p1 $p1_min $p1_max $p2 $p2_min $p2_max $p3_red $p3_green $p3_blue $p4 ";
    exit 0;
}

if ($command eq "onchange_init") {
    $p1=@ARGV[1];
    $p1_min=@ARGV[2];
    $p1_max=@ARGV[3];
    $p2=@ARGV[4];
    $p2_min=@ARGV[5];
    $p2_max=@ARGV[6];
    $p3_red=@ARGV[7];
    $p3_green=@ARGV[8];
    $p3_blue=@ARGV[9];
    $p4=@ARGV[10];
    $width=@ARGV[11];
    $height=@ARGV[12];
    $start=@ARGV[13];
    $end=@ARGV[14];
    $last=@ARGV[15];
    $length=$end-$start+1;

    $p1_max=$length-1;$p2=$p2_max=$length-$p1;if ($p2_max<$p2_min) {$p2=$p2_max=$p2_min;}

    print "$p1 $p1_min $p1_max $p2 $p2_min $p2_max $p3_red $p3_green $p3_blue $p4 ";
    exit 0;
}
