######################################################################
#
# MultimediaPlugin.pm -- internal plugin to support processing audio and video
# A component of the Greenstone digital library software
# from the New Zealand Digital Library Project at the 
# University of Waikato, New Zealand.
#
# Copyright (C) 1999 New Zealand Digital Library Project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###########################################################################

# -- Largely modeled on how ImagePlugin works 

package MultimediaPlugin;

use strict;
no strict 'refs'; # allow filehandles to be variables and viceversa
no strict 'subs';

use gsprintf;

use BaseImporter;

sub BEGIN {
    @MultimediaPlugin::ISA = ('BaseImporter');

    if (!defined $ENV{'GEXTVIDEO'}) {
	print STDERR "Warning: Greenstone Video extension not detected.\n";
    }

}



 # do later the description
my $arguments =
    [ { 'name' => "use_ascii_only_filenames",
	'desc' => "{VideoPlug.use_ascii_only_filenames}",
	'type' => "flag",
	'reqd' => "no" },
      { 'name' => "excerpt_duration",
	'desc' => "{MultimediaPlug.excerpt_duration}",
	'type' => "string",
	'deft' => "",
	'reqd' => "no" },
      { 'name' => "converttotype",
	'desc' => "{MultimediaPlug.converttotype}",
	'type' => "string",
	'deft' => "",
	'reqd' => "no" },
	  { 'name' => "enable_streaming",
	'desc' => "{MultimediaPlug.enable_streaming}",
	'type' => "enum",
	'list' => [{'name' => "disabled", 'desc' => "Do not create any video file optimised for streaming over the Internet."},
		       {'name' => "flv", 'desc' => "Uses the FLV format for streaming media. Better to target old computers."},
		       {'name' => "mp4", 'desc' => "Uses the MP4 container with H264 and AAC codecs. Better quality at very low bitrates but more ressources intensive."},
			   {'name' => "direct", 'desc' => "Uses the original video file for direct streaming. The video player should be compatible with the format used!"}],
	'deft' => "disabled",
	'reqd' => "no" }];

my $options = { 'name'     => "MultimediaPlugin",
		'desc'     => "{MultimediaPlug.desc}",
		'abstract' => "yes",
		'inherits' => "yes",
		'args'     => $arguments };


sub new {
    my ($class) = shift (@_);
    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
    push(@$pluginlist, $class);

    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
    push(@{$hashArgOptLists->{"OptList"}},$options);

    my $self = new BaseImporter($pluginlist, $inputargs, $hashArgOptLists);

    # Check that ffmpeg is installed and available on the path (except for Windows 95/98)
    # This test is "inherited" from ImagePlugin where ImageMagick support
    # for building cannot be used on these two versions of Windows as they
    # do not have enough flexablity in the use of stdout and stderr to
    # support how our code works.  It seems reasonable to assume the
    # same is true for MultimediaPlugin work using ffmpeg.

    if (($ENV{'GSDLOS'} ne "windows" || Win32::IsWinNT())) {

##	my $result = `ffmpeg -h 2>&1`;
	my $result = `ffmpeg -version 2>&1`;

	if (!defined $result || $result !~ m/^FFmpeg\s+version/mi) {
	    $self->{'ffmpeg_installed'} = 0;
	    if (defined $result) {
		print STDERR "Problem detecting ffmpeg:\n";
		print STDERR $result;
	    }
	    else {
		print STDERR "Unable to find ffmpeg\n";
	    }
	}
	else {
	    $self->{'ffmpeg_installed'} = 1;
	}

    }

    return bless $self, $class;
}



sub begin {
    my $self = shift (@_);
    my ($pluginfo, $base_dir, $processor, $maxdocs) = @_;

    $self->SUPER::begin(@_);

    $self->{'base_dir'} = $base_dir;
}


sub init {
    my $self = shift (@_);
    my ($verbosity, $outhandle, $failhandle) = @_;

    $self->SUPER::init(@_);
}

# Want to hash on doc.xml rather than original file which in the case of 
# audio and video can be HUGE

sub get_oid_hash_type {

    my $self = shift (@_);

    return "hash_on_ga_xml";
}



# Create the keyframes, thumbnail and screenview images, and discover
# the Video's size, width, and height using the ffmpeg utility.

sub run_convert {
    my $self = shift (@_);

    die "$self The inheriting class must implement run_convert method";
}


sub read_into_doc_obj {
    my $self = shift (@_);  
    my ($pluginfo, $base_dir, $file, $block_hash, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;

    my $outhandle = $self->{'outhandle'};

    # should we move this to read? What about secondary plugins?
    print STDERR "<Processing n='$file' p='$self->{'plugin_type'}'>\n" if ($gli);
    print $outhandle "$self->{'plugin_type'} processing $file\n"
	    if $self->{'verbosity'} > 1;

    my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);

    # create a new document
    my $doc_obj = new doc ($filename_full_path, "indexed_doc", $self->{'file_rename_method'});


    my $top_section = $doc_obj->get_top_section();


    $doc_obj->add_utf8_metadata($top_section, "Plugin", "$self->{'plugin_type'}");
    $doc_obj->add_utf8_metadata($top_section, "FileSize", (-s $filename_full_path));
 
    # sets the UTF8 filename (Source) for display and sets the url ref to URL encoded version
    # of the UTF8 filename (SourceFile) for generated files
    $self->set_Source_metadata($doc_obj, $filename_no_path);


    # plugin specific stuff - what args do we need here??
    unless (defined ($self->process($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli))) {
	print STDERR "<ProcessingError n='$file'>\n" if ($gli);
	return (-1,undef);
    }
    
    # include any metadata passed in from previous plugins 
    # note that this metadata is associated with the top level section
    my $section = $doc_obj->get_top_section();
    # can we merge these two methods??
    $self->add_associated_files($doc_obj, $filename_full_path);
    $self->extra_metadata ($doc_obj, $section, $metadata);
    $self->auto_extract_metadata($doc_obj);

    # if we haven't found any Title so far, assign one
    # this was shifted to here from inside read()
    $self->title_fallback($doc_obj,$section,$filename_no_path);
    
    $self->add_OID($doc_obj);

    $self->post_process_doc_obj($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli);

    return (1,$doc_obj);
}

sub add_dummy_text {
    my $self = shift(@_);
    my ($doc_obj, $section) = @_;

    # add NoText metadata so we can hide this dummy text in format statements
    $doc_obj->add_metadata($section, "NoText", "1");
    $doc_obj->add_text($section, &gsprintf::lookup_string("{BaseImporter.dummy_text}",1));
    
}




# do plugin specific processing of doc_obj
sub process {
    my $self = shift (@_);
    # options??
    my ($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;

    my $outhandle = $self->{'outhandle'};

    my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);


    if ($self->{'ffmpeg_installed'}) {
	my $utf8_filename_no_path = $self->filepath_to_utf8($filename_no_path);
	my $url_encoded_filename = &util::rename_file($utf8_filename_no_path, $self->{'file_rename_method'});


	#run convert to get the thumbnail and extract size and type info
	my $result = $self->run_convert($base_dir, $filename_full_path, 
					$url_encoded_filename, $doc_obj);
	
	if (!defined $result) {
	    if ($gli) {
		print STDERR "<ProcessingError n='$file'>\n";
	    }
	    print $outhandle "MultimediaPlugin: couldn't process \"$filename_full_path\"\n";
	    return (-1,undef); # error during processing
	}
    } 
    else {
	if ($gli) {
	    &gsprintf(STDERR, "<Warning p='MultimediaPlugin' r='{MultimediaConverter.noconversionavailable}: {MultimediaConverter.".$self->{'no_multimedia_conversion_reason'}."}'>");
	}
	# all we do is add the original video file as an associated file, and set up srclink etc
	my $assoc_file = $doc_obj->get_assocfile_from_sourcefile();
	my $section = $doc_obj->get_top_section();

	$doc_obj->associate_file($filename_full_path, $assoc_file, "", $section);

	$doc_obj->add_metadata ($section, "srclink", "<a href=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[SourceFile]\">");
	$doc_obj->add_metadata ($section, "/srclink", "</a>");
	$doc_obj->add_metadata ($section, "srcicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[SourceFile]\" width=\"100\">");

    }
    #we have no text - adds dummy text and NoText metadata
    $self->add_dummy_text($doc_obj, $doc_obj->get_top_section());

    return 1;

}



1;











