diff --git a/scripts/Makefile.am b/scripts/Makefile.am index dd731dc73..640f13b28 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -1,5 +1,5 @@ AUTOMAKE_OPTIONS = gnu -bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl zmpkg.pl +bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl zmpkg.pl zmvideo.pl -EXTRA_DIST = zmdc.pl.z zmaudit.pl.z zmfilter.pl.z zmx10.pl.z zmwatch.pl.z zmpkg.pl.z zm.z +EXTRA_DIST = zmdc.pl.z zmaudit.pl.z zmfilter.pl.z zmx10.pl.z zmwatch.pl.z zmpkg.pl.z zmvideo.pl.z zm.z diff --git a/scripts/Makefile.in b/scripts/Makefile.in index 2c8ea44f8..d167ef6a8 100644 --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -117,9 +117,9 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = gnu -bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl zmpkg.pl +bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl zmpkg.pl zmvideo.pl -EXTRA_DIST = zmdc.pl.z zmaudit.pl.z zmfilter.pl.z zmx10.pl.z zmwatch.pl.z zmpkg.pl.z zm.z +EXTRA_DIST = zmdc.pl.z zmaudit.pl.z zmfilter.pl.z zmx10.pl.z zmwatch.pl.z zmpkg.pl.z zmvideo.pl.z zm.z subdir = scripts mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h diff --git a/scripts/zmfilter.pl.z b/scripts/zmfilter.pl.z index 585bc9eff..03e18cf8b 100755 --- a/scripts/zmfilter.pl.z +++ b/scripts/zmfilter.pl.z @@ -86,7 +86,7 @@ my $email_subject; my $email_body; if ( ZM_OPT_EMAIL ) { - use Mail::Mailer; + use MIME::Entity; use constant ZM_EMAIL_FORMAT => ""; # File containing the contents of the email @@ -97,7 +97,7 @@ my $message_subject; my $message_body; if ( ZM_OPT_MESSAGE ) { - use Mail::Mailer; + use MIME::Entity; use constant ZM_MESSAGE_FORMAT => ""; # File containing the contents of the message @@ -475,25 +475,35 @@ sub sendEmail print( "Creating notification email\n" ); - my $subject = substituteTags( $email_subject, $filter, $event ); - my $body = substituteTags( $email_body, $filter, $event ); + my $subject = substituteTags( $email_subject, $filter, \$event ); + my $body = substituteTags( $email_body, $filter, \$event ); print( "Sending notification email '$subject'\n" ); print( "$body\n" ) if ( VERBOSE ); eval { - my $mailer = new Mail::Mailer; - - $mailer->open( { + my $mail = MIME::Entity->build( + From =>ZM_FROM_EMAIL, + To=>ZM_EMAIL_ADDRESS, Subject=>$subject, - From=>ZM_FROM_EMAIL, - To=>ZM_EMAIL_ADDRESS - } ); + Data=>$body + ); - print( $mailer $body ); + if ( $event->{attachments} ) + { + foreach my $attachment ( @{$event->{attachments}} ) + { + print( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path=>$attachment->{path}, + Type=>$attachment->{type}, + Encoding=>"base64" + ); + } + } - $mailer->close(); + $mail->smtpsend(); }; if ( $@ ) { @@ -521,27 +531,37 @@ sub sendMessage return; } - print( "Creating notification email\n" ); + print( "Creating notification message\n" ); - my $subject = substituteTags( $message_subject, $filter, $event ); - my $body = substituteTags( $message_body, $filter, $event ); + my $subject = substituteTags( $message_subject, $filter, \$event ); + my $body = substituteTags( $message_body, $filter, \$event ); print( "Sending notification message '$subject'\n" ); print( "$body\n" ) if ( VERBOSE ); eval { - my $mailer = new Mail::Mailer; - - $mailer->open( { + my $mail = MIME::Entity->build( + From =>ZM_FROM_EMAIL, + To=>ZM_MESSAGE_ADDRESS, Subject=>$subject, - From=>ZM_FROM_EMAIL, - To=>ZM_MESSAGE_ADDRESS - } ); + Data=>$body + ); - print( $mailer $body ); + if ( $event->{attachments} ) + { + foreach my $attachment ( @{$event->{attachments}} ) + { + print( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path=>$attachment->{path}, + Type=>$attachment->{type}, + Encoding=>"base64" + ); + } + } - $mailer->close(); + $mail->smtpsend(); }; if ( $@ ) { @@ -557,7 +577,8 @@ sub substituteTags { my $text = shift; my $filter = shift; - my $event = shift; + my $event_ref = shift; + my $event = $$event_ref; # First we'd better check what we need to get # We have a filter and an event, do we need any more @@ -576,7 +597,7 @@ sub substituteTags } # Do we need the image information too? - my $need_images = $text =~ /%(?:EPI1|EPIM)%/; + my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM)%/; my @frames = (); my $first_alarm_frame; my $max_alarm_frame; @@ -630,6 +651,30 @@ sub substituteTags $text =~ s/%ESM%/$event->{MaxScore}/g; $text =~ s/%EPI1%/$url?view=image&mid=$filter->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g; $text =~ s/%EPIM%/$url?view=image&mid=$filter->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g; + if ( $text =~ s/%EI1%/First alarm frame attached/g ) + { + my $attachments = $event->{attachments}; + $attachments = $event->{attachments} = [] if ( !$attachments ); + push( @$attachments, { type=>"image/jpeg", path=>sprintf( "%s/%d/capture-%03d.jpg", $filter->{MonitorName}, $event->{Id}, $first_alarm_frame->{FrameId} ) } ); + } + if ( $text =~ s/%EIM%/Max alarm frame attached/g ) + { + my $attachments = $event->{attachments}; + $attachments = $event->{attachments} = [] if ( !$attachments ); + push( @$attachments, { type=>"image/jpeg", path=>sprintf( "%s/%d/capture-%03d.jpg", $filter->{MonitorName}, $event->{Id}, $max_alarm_frame->{FrameId} ) } ); + } + if ( $text =~ s/%EV%/Event video attached/g ) + { + my $attachments = $event->{attachments}; + $attachments = $event->{attachments} = [] if ( !$attachments ); + my $command = ZM_PATH_BIN."/zmvideo.pl -e $event->{Id}"; + my $output = qx($command); + my $status = $? >> 8; + if ( $status == 0 ) + { + push( @$attachments, { type=>"video/mpeg", path=>sprintf( "%s/%d/%s", $filter->{MonitorName}, $event->{Id}, $output ) } ); + } + } $text =~ s/%FN%/$filter->{Name}/g; ( my $filter_name = $filter->{Name} ) =~ s/ /+/g; $text =~ s/%FP%/$url?view=filter&mid=$filter->{MonitorId}&filter_name=$filter_name/g; diff --git a/scripts/zmvideo.pl.z b/scripts/zmvideo.pl.z new file mode 100644 index 000000000..f158381d3 --- /dev/null +++ b/scripts/zmvideo.pl.z @@ -0,0 +1,164 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Video Creation Script, $Date$, $Revision$ +# Copyright (C) 2003 Philip Coombes +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ========================================================================== +# +# This script is used to create MPEG videos of events for the web pages +# or as email attachments. +# +use strict; + +# ========================================================================== +# +# These are the elements you need to edit to suit your installation +# +# ========================================================================== +use constant ZM_PATH_BIN => ""; +use constant ZM_PATH_WEB => ""; +use constant ZM_PATH_CGI => ""; +use constant ZM_PATH_LOGS => ""; +use constant ZM_PATH_NETPBM => ""; +use constant ZM_PATH_MPEG_ENCODE => ""; +use constant ZM_DB_SERVER => ""; +use constant ZM_DB_NAME => ""; +use constant ZM_DB_USERB => ""; +use constant ZM_DB_PASSB => ""; +use constant ZM_DIR_EVENTS => ""; + +use constant LOG_FILE => ZM_PATH_LOGS.'/zmvideo.log'; +use constant VERBOSE => 0; # Whether to output more verbose debug + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +use DBI; +use Data::Dumper; +use Getopt::Long; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $event_id; + +sub Usage +{ + print( " +Usage: zmvideo.pl -e ,--event= +Parameters are :- +-e, --event= - What event to start create the video for +"); + exit( -1 ); +} + +if ( !GetOptions( 'event=i'=>\$event_id ) ) +{ + Usage(); +} + +if ( !$event_id || $event_id < 0 ) +{ + print( STDERR "Please give a valid event id\n" ); + Usage(); +} + +my $log_file = LOG_FILE; +open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" ); +#open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" ); +#select( STDOUT ); $| = 1; +open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" ); +select( STDERR ); $| = 1; +select( LOG ); $| = 1; + +my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USERB, ZM_DB_PASSB ); + +my @filters; +my $sql = "select E.*,M.Name as MonitorName, M.Palette from Events as E inner join Monitors as M on E.MonitorId = M.Id where E.Id = '$event_id'"; +my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); +my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); +my $event = $sth->fetchrow_hashref(); +$sth->finish(); +chdir( ZM_PATH_WEB.'/'.ZM_DIR_EVENTS.'/'.$event->{MonitorName}.'/'.$event->{Id} ); +( my $video_name = $event->{Name} ) =~ s/\s/_/g; +my $param_file = "$video_name.mpe"; +my $video_file = "$video_name.mpg"; + +if ( !-s $video_file ) +{ + print( LOG "Creating video file $video_file for event $event->{Id}\n" ); + open( PARAMS, ">$param_file" ) or die( "Can't open '$param_file': $!" ); + + print( PARAMS "PATTERN IBBPBBPBBPBBPBB\n" ); + print( PARAMS "OUTPUT $video_file\n" ); + + print( PARAMS "BASE_FILE_FORMAT JPEG\n" ); + print( PARAMS "GOP_SIZE 30\n" ); + print( PARAMS "SLICES_PER_FRAME 1\n" ); + + print( PARAMS "PIXEL HALF\n" ); + print( PARAMS "RANGE 10\n" ); + print( PARAMS "PSEARCH_ALG LOGARITHMIC\n" ); + print( PARAMS "BSEARCH_ALG CROSS2\n" ); + print( PARAMS "IQSCALE 8\n" ); + print( PARAMS "PQSCALE 10\n" ); + print( PARAMS "BQSCALE 25\n" ); + + print( PARAMS "REFERENCE_FRAME ORIGINAL\n" ); + print( PARAMS "FRAME_RATE 24\n" ); + + if ( $event->{Palette} == 1 ) + { + print( PARAMS "INPUT_CONVERT ".ZM_PATH_NETPBM."/jpegtopnm * | ".ZM_PATH_NETPBM."/pgmtoppm white | ".ZM_PATH_NETPBM."/ppmtojpeg\n" ); + } + else + { + print( PARAMS "INPUT_CONVERT *\n" ); + } + print( PARAMS "INPUT_DIR .\n" ); + + print( PARAMS "INPUT\n" ); + for ( my $i = 1; $i <= $event->{Frames}; $i++ ) + { + printf( PARAMS "capture-%03d.jpg\n", $i ); + } + print( PARAMS "END_INPUT\n" ); + close( PARAMS ); + + my $command = ZM_PATH_MPEG_ENCODE." $param_file >mpeg.log"; + my $output = qx($command); + my $status = $? >> 8; + if ( $status ) + { + die( "Error: $status" ); + } +} +else +{ + print( LOG "Video file $video_file already exists for event $event->{Id}\n" ); +} +#print( STDOUT $event->{MonitorName}.'/'.$event->{Id}.'/'.$video_file."\n" ); +print( STDOUT $video_file."\n" ); +exit( 0 ); diff --git a/web/zm_funcs.php b/web/zm_funcs.php index 70fea0d6e..4fd25c8bc 100644 --- a/web/zm_funcs.php +++ b/web/zm_funcs.php @@ -202,4 +202,12 @@ function zmaCheck( $monitor ) } return( daemonCheck( "zma", "-m $monitor" ) ); } + +function createVideo( $event ) +{ + $command = ZM_PATH_BIN."/zmvideo.pl -e $event[Id]"; + $result = exec( $command, $output, $status ); + return( $status?"":$result ); +} + ?> diff --git a/web/zm_html.php b/web/zm_html.php index 1afb37d1d..6edafbf3d 100644 --- a/web/zm_html.php +++ b/web/zm_html.php @@ -2465,57 +2465,12 @@ function closeWindow() die( mysql_error() ); $event = mysql_fetch_assoc( $result ); - $event_dir = ZM_DIR_EVENTS."/$event[MonitorName]/".sprintf( "%d", $eid ); - $param_file = $event_dir."/mpeg.param"; - $video_name = preg_replace( "/\\s/", "_", $event[Name] ).".mpeg"; - $video_file = $event_dir."/".$video_name; - - if ( !file_exists( $video_file ) ) + if ( $video_file = createVideo( $event ) ) { - $fp = fopen( $param_file, "w" ); - - fputs( $fp, "PATTERN IBBPBBPBBPBBPBB\n" ); - fputs( $fp, "OUTPUT $video_file\n" ); - - fputs( $fp, "BASE_FILE_FORMAT JPEG\n" ); - fputs( $fp, "GOP_SIZE 30\n" ); - fputs( $fp, "SLICES_PER_FRAME 1\n" ); - - fputs( $fp, "PIXEL HALF\n" ); - fputs( $fp, "RANGE 10\n" ); - fputs( $fp, "PSEARCH_ALG LOGARITHMIC\n" ); - fputs( $fp, "BSEARCH_ALG CROSS2\n" ); - fputs( $fp, "IQSCALE 8\n" ); - fputs( $fp, "PQSCALE 10\n" ); - fputs( $fp, "BQSCALE 25\n" ); - - fputs( $fp, "REFERENCE_FRAME ORIGINAL\n" ); - fputs( $fp, "FRAME_RATE 24\n" ); - - if ( $event[Palette] == 1 ) - fputs( $fp, "INPUT_CONVERT ".ZM_PATH_NETPBM."/jpegtopnm * | ".ZM_PATH_NETPBM."/pgmtoppm white | ".ZM_PATH_NETPBM."/ppmtojpeg\n" ); - else - fputs( $fp, "INPUT_CONVERT *\n" ); - - fputs( $fp, "INPUT_DIR $event_dir\n" ); - - fputs( $fp, "INPUT\n" ); - for ( $i = 1; $i < $event[Frames]; $i++ ) - { - fputs( $fp, "capture-".sprintf( "%03d", $i ).".jpg\n" ); - fputs( $fp, "capture-".sprintf( "%03d", $i ).".jpg\n" ); - } - fputs( $fp, "END_INPUT\n" ); - fclose( $fp ); - - exec( ZM_PATH_MPEG_ENCODE." $param_file >$event_dir/mpeg.log" ); + $event_dir = ZM_DIR_EVENTS."/$event[MonitorName]/".sprintf( "%d", $eid ); + $video_path = $event_dir.'/'.$video_file; + header("Location: $video_path" ); } - - //chdir( $event_dir ); - //header("Content-type: video/mpeg"); - //header("Content-Disposition: inline; filename=$video_name"); - header("Location: $video_file" ); - break; } case "function" : diff --git a/zmconfig_eml.txt b/zmconfig_eml.txt index ea89fc54b..0bc1a34ff 100644 --- a/zmconfig_eml.txt +++ b/zmconfig_eml.txt @@ -18,6 +18,9 @@ # %EPI% - The path to the event images # %EPI1% - The path to the first alarmed event image # %EPIM% - The path to the (first) event image with the highest score +# %EI1% - Attach first alarmed event image +# %EIM% - Attach (first) event image with the highest score +# %EV% - Attach event mpeg video # %EI% - The id of the event # %EN% - The name of the event # %ET% - The time of the event @@ -63,6 +66,9 @@ This alarm was matched by the %FN% filter and can be viewed at %EPS% # %EPI% - The path to the event images # %EPI1% - The path to the first alarmed event image # %EPIM% - The path to the (first) event image with the highest score + # %EI1% - Attach first alarmed event image + # %EIM% - Attach (first) event image with the highest score + # %EV% - Attach event mpeg video # %EI% - The id of the event # %EN% - The name of the event # %ET% - The time of the event diff --git a/zmconfig_msg.txt b/zmconfig_msg.txt index 4e4561a6a..ff60ede6a 100644 --- a/zmconfig_msg.txt +++ b/zmconfig_msg.txt @@ -21,6 +21,9 @@ # %EPI% - The path to the event images # %EPI1% - The path to the first alarmed event image # %EPIM% - The path to the (first) event image with the highest score +# %EI1% - Attach first alarmed event image +# %EIM% - Attach (first) event image with the highest score +# %EV% - Attach event mpeg video # %EI% - The id of the event # %EN% - The name of the event # %ET% - The time of the event