# ==================================================================
# Plugins::ConvertVideo - Auto Generated Program Module
#
#   Plugins::ConvertVideo
#   Author  : Virginia Lo
#   Version : 1.1
#   Updated : Wed Feb 21 16:05:27 2007
#
# ==================================================================
#

package Plugins::ConvertVideo;

# ==================================================================

use strict;
use GT::Base;
use GT::Plugins qw/STOP CONTINUE/;
use Links qw/$CFG $IN $DB/;
use Links::Plugins;
use vars qw/$WIDTH $HEIGHT $LINKID $CONVERTBOX $CHECKCONVERTBOX/;

# Inherit from base class for debug and error methods
@Plugins::ConvertVideo::ISA = qw(GT::Base);

# Your code begins here! Good Luck!

# PLUGIN HOOKS
# ===================================================================

sub validate_link_pre {
# -------------------------------------------------------------------
# This subroutine will get called whenever the hook 'validate_link'
# is run. You should call GT::Plugins->action (STOP) if you don't
# want the regular code to run, otherwise the code will continue as
# normal.
#
    my ($link) = @_;
    $link = convert_video($link);
    return $link;
}

sub pre_form_link {
# -------------------------------------------------------------------
#
    my $opts = shift;
    if ($opts->{mode} =~ /([add|modify])_form/) {
        $CONVERTBOX = 1;

        if ($1 eq 'add') {
            $CHECKCONVERTBOX = 1;
        }
    }
    return $opts;
}

sub post_form_link {
# -------------------------------------------------------------------
#
    my @args = @_;
    if (($CONVERTBOX and $IN->param('db') eq 'Links')
        || $IN->param('action') eq 'link_add_form' 
        || $IN->param('action') eq 'link_modify_form')
    {
        my $checked = '';
        if ($IN->param('action') eq 'link_add_form' || $CHECKCONVERTBOX) {
            $checked = ' checked';
        }

        my $font = 'face="Tahoma,Arial,Helvetica" size="2"';
        $args[0] .=
qq~<p><table border=1 cellpadding=0 bgcolor="#FFFFFF" cellspacing=0 width="500"><tr><td>
        <table border=0 bgcolor="#FFFFFF" width="500"><tr>
        <td width="20%" valign="top"><font $font>Converting Video(s)?</td>
        <td width="80%"><font $font><input type="checkbox" name="admin_convert_video" value="1"$checked/> YES </td>
    </tr></table>
    </td></tr></table>~;
    }
    return @args;
}

sub modify_link_pre {
# -------------------------------------------------------------------
# This subroutine will get called whenever the hook 'modify_link'
# is run. You should call GT::Plugins->action (STOP) if you don't
# want the regular code to run, otherwise the code will continue as
# normal.
#
    my @args = @_;
    my $link = $args[0];
    $LINKID = $link->{ID};
    return @args;
}

sub modify_link_post {
# -------------------------------------------------------------------
#
    my $ret = shift;
    if ($ret and $LINKID and $IN->param('admin_convert_video')) {
        my $linkdb = $DB->table('Links');
        my $link   = convert_video({ ID => $LINKID });
        my $res    = $linkdb->update($link, { ID => $LINKID });
        if (!$res) {
            die "Can't modify link #$LINKID: $GT::SQL::error\n";
        }
    }
    return $ret;
}

sub add_link_post {
# -------------------------------------------------------------------
#
    $LINKID = shift;
    if ($LINKID) {
        &modify_link_post(1);
    }
    return $LINKID;
}

sub convert_video {
# ------------------------------------------------------------------
# Grab video details
    my ($link) = @_;

    my $linksdb = $DB->table('Links');
    my $cfg     = Links::Plugins::get_plugin_user_cfg('ConvertVideo');

    my $vf_field = $cfg->{video_file_field};
    my $ff_field = $cfg->{flash_file_field};
    my $thumb    = $cfg->{thumbnail_file_field};
    my $image    = $cfg->{image_file_field};

    my $fh = $linksdb->file_info($vf_field, $link->{ID}) or return $link;

    my $full_path = "$fh";
    my $video     = {};

    my $filename = $full_path;
    $filename =~ s/(.+)\/\d-([^\/]+)\.$/$2/g;

    my $flv_file_path =
      $CFG->{admin_root_path} . "/tmp/" . $link->{ID} . ".flv";
    my $thumb_path =
      $CFG->{admin_root_path} . "/tmp/" . "thumbnail-" . $link->{ID} . ".png";
    my $image_path =
      $CFG->{admin_root_path} . "/tmp/" . "image-" . $link->{ID} . ".png";

    my $buf = `ffmpeg -i "$full_path" 2>&1`;

    if ($cfg->{flash_dimension} =~ /\s*(\d+)x(\d+)\s*/) {
        ($WIDTH, $HEIGHT) = ($1, $2);
    }

    if ($buf =~ /Video:.+\s+(\d+)x(\d+),?.*\s+(\d+\.\d+)\s+(?:fps|tb)/) {
        $video->{width}  = $1;
        $video->{height} = $2;
        $video->{fps}    = $3;

        if ($buf =~ /Duration:\s+(\d+):(\d+):(\d+).+bitrate:\s+(\d+)\s+kb\/s/)
        {
            $video->{duration} = $1 * 3600 + $2 * 60 + $3;
            $video->{bitrate}  = $4;
        }

    } else {
        warn "Couldn't get video info";
        return $link;
    }

    # Figure out any scaling we might need to do
    if ($video->{width} > $WIDTH and $video->{height} > $HEIGHT) {

        # Choose the larger dimension to scale down
        if ($video->{width} / $WIDTH > $video->{height} / $HEIGHT) {
            $video->{out_height} =
              int($video->{height} * $WIDTH / $video->{width});
            $video->{out_width} = $WIDTH;
        } else {
            $video->{out_width} =
              int($video->{width} * $HEIGHT / $video->{height});
            $video->{out_height} = $HEIGHT;
        }
    } elsif ($video->{width} > $WIDTH) {
        $video->{out_height} = int($HEIGHT * $WIDTH / $video->{width});
        $video->{out_width}  = $WIDTH;
    } elsif ($video->{height} > $HEIGHT) {
        $video->{out_height} = $HEIGHT;
        $video->{out_width}  = int($video->{height} * $WIDTH / $HEIGHT);
    }

    # Source dimensions are smaller than output
    else {
        $video->{out_height} = $video->{height};
        $video->{out_width}  = $video->{width};
    }

    $video->{out_height}++ if $video->{out_height} % 2;
    $video->{out_width}++  if $video->{out_width} % 2;

    $video->{out_padtop} = int(($HEIGHT - $video->{out_height}) / 2);
    $video->{out_padtop}-- if $video->{out_padtop} % 2;
    $video->{out_padbottom} =
      $HEIGHT - $video->{out_height} - $video->{out_padtop};

    $video->{out_padleft} = int(($WIDTH - $video->{out_width}) / 2);
    $video->{out_padleft}-- if $video->{out_padleft} % 2;
    $video->{out_padright} =
      $WIDTH - $video->{out_width} - $video->{out_padleft};

    # Encode the video
    system(
        "ffmpeg",
        '-i', "$full_path",
        '-y',    # overwrite
                 # video options
        '-r',         $video->{fps},                                # frame rate
        '-s',         "$video->{out_width}x$video->{out_height}",   # frame size
        '-padtop',    $video->{out_padtop},
        '-padbottom', $video->{out_padbottom},
        '-padleft',   $video->{out_padleft},
        '-padright',  $video->{out_padright},

        # audio options
        '-ar', 22050,    # audio sampling rate (Hz)
        '-ab', 64,       # audio bitrate (kb/s)
        '-ac', 2,        # audio channels
                         # encoding options
                         #            '-b', 100000, # video bitrate (b/s)
        '-qscale',
        $cfg->{flash_quality} || 6,    # quality scale (1 [best] - 31 [worst])
                                       # watermark
          #            '-vhook', '/usr/lib/vhook/watermark.so -f admin/water3.gif',
          # output
        "$flv_file_path",
   );

=tag
# video options
                '-r', $video->{fps}, # frame rate
                '-s', "$video->{out_width2}x$video->{out_height2}", # frame size
                '-padtop', $video->{out_padtop},
                '-padbottom', $video->{out_padbottom},
                '-padleft', $video->{out_padleft},
                '-padright', $video->{out_padright},
=cut

# -----------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------

    # Generate a thumbnail (a quarter of the way through)
    my $when  = int($video->{duration} * 0.25);
    my $hours = int($when / 3600);
    my $mins  = int($when / 60) - $hours * 60;
    my $secs  = $when - $hours * 3600 - $mins * 60;
    $when = sprintf("%.2d:%.2d:%.2d", $hours, $mins, $secs);

    if ($cfg->{thumbnail_size} and $cfg->{thumbnail_file_field}) {
        system(
            "ffmpeg",
            '-i', "$flv_file_path",
            '-y',    # overwrite
            '-vframes', 1,       # record 1 frame
            '-ss',      $when,
            '-an',               # no audio
            '-vcodec', 'png',
            '-f',      'rawvideo',
            '-s',      $cfg->{thumbnail_size},
            "$thumb_path",
       );
    }

    system(
        "ffmpeg",
        '-i', "$flv_file_path",
        '-y',                    # overwrite
        '-vframes', 1,           # record 1 frame
        '-ss',      $when,
        '-an',                   # no audio
        '-vcodec', 'png',
        '-f',      'rawvideo',
        '-s',      "${WIDTH}x$HEIGHT",    # frame size
        "$image_path",
   );

    $link->{$ff_field} = GT::SQL::File->open($flv_file_path);
    $link->{$image}         = GT::SQL::File->open($image_path);
    $link->{$thumb}      = GT::SQL::File->open($thumb_path)
      if ($cfg->{thumbnail_file_field} and $thumb_path);

    return $link;

}

sub get_file_path {
# ---------------------------------------------------------------------------
# return file path of a file column
#
    my $cfg        = Links::Plugins::get_plugin_user_cfg('ConvertVideo');
    my $id         = shift;
    my $field_name = shift || "flash_file_field";
    my $field      = $cfg->{$field_name};
    my $wantpath   = shift || 0;
    my $fh         = $DB->table('Links')->file_info($field, $id);
    return { $field_name . "_path" => '' } if (!$fh);
    my $fdir      = $fh->File_Directory();
    my $full_path = "$fh";
    my $rel_path  = $full_path;
    $rel_path =~ s,$fdir,,;
    $rel_path =~ s,%,%25,g;

    if ($wantpath) {
        return $rel_path;
    }
    return { $field_name . "_path" => $cfg->{video_url} . $rel_path };
}

sub get_flash_dimension {
    my $cfg    = Links::Plugins::get_plugin_user_cfg('ConvertVideo');
    my $width  = 320;
    my $height = 240;
    if ($cfg->{flash_dimension} =~ /\s*(\d+)x(\d+)\s*/) {
        ($width, $height) = ($1, $2);
    }

    return { 'video_width' => $width, 'video_height' => $height };
}

sub get_video_max_size {
    my $cfg        = Links::Plugins::get_plugin_user_cfg('ConvertVideo');
    my $field_name = $cfg->{video_file_field};
    my %cols = $DB->table('Links')->_file_cols();
    return $cols{$field_name}->{file_max_size};
}

# Always end with a 1.
1;
