diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index ce462ac4c..2c287d7a9 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -445,6 +445,10 @@ CREATE TABLE `Monitors` ( `Enabled` tinyint(3) unsigned NOT NULL default '1', `LinkedMonitors` varchar(255), `Triggers` set('X10') NOT NULL default '', + `ONVIF_URL` VARCHAR(255) NOT NULL DEFAULT '', + `ONVIF_Username` VARCHAR(64) NOT NULL DEFAULT '', + `ONVIF_Password` VARCHAR(64) NOT NULL DEFAULT '', + `ONVIF_Options` VARCHAR(64) NOT NULL DEFAULT '', `Device` tinytext NOT NULL default '', `Channel` tinyint(3) unsigned NOT NULL default '0', `Format` int(10) unsigned NOT NULL default '0', diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm index 06c116626..acce8eb4a 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm @@ -116,7 +116,7 @@ sub getParam { } elsif ( defined($default) ) { return $default; } - Fatal("Missing mandatory parameter '$name'"); + Error("Missing mandatory parameter '$name'"); } sub executeCommand { diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 39c10a058..0513f563e 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -210,7 +210,7 @@ sub initialise( @ ) { if ( my $logFile = $this->getTargettedEnv('LOG_FILE') ) { $tempLogFile = $logFile; } - ($tempLogFile) = $tempLogFile =~ /^([\w\.\/]+)$/; + ($tempLogFile) = $tempLogFile =~ /^([_\-\w\.\/]+)$/; my $tempLevel = INFO; my $tempTermLevel = $this->{termLevel}; @@ -456,9 +456,9 @@ sub fileLevel { if ( defined($fileLevel) ) { $fileLevel = $this->limit($fileLevel); # The filename might have changed, so always close and re-open - $this->closeFile() if ( $this->{fileLevel} > NOLOG ); + $this->closeFile() if $this->{fileLevel} > NOLOG; $this->{fileLevel} = $fileLevel; - $this->openFile() if ( $this->{fileLevel} > NOLOG ); + $this->openFile() if $this->{fileLevel} > NOLOG; } return $this->{fileLevel}; } @@ -499,6 +499,7 @@ sub logFile { sub openFile { my $this = shift; + if ( open($LOGFILE, '>>', $this->{logFile}) ) { $LOGFILE->autoflush() if $this->{autoFlush}; @@ -519,7 +520,6 @@ sub openFile { } sub closeFile { - #my $this = shift; close($LOGFILE) if fileno($LOGFILE); } diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ONVIF.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ONVIF.pm.in index 86cb859c6..d90a5fea3 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ONVIF.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ONVIF.pm.in @@ -39,12 +39,10 @@ our %EXPORT_TAGS = ( ); push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; -our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } ); our @EXPORT = qw(); -our $VERSION = $ZoneMinder::Base::VERSION; - use Data::UUID; use vars qw( $verbose $soap_version ); @@ -60,6 +58,9 @@ require WSDiscovery::TransportUDP; sub deserialize_message { my ($wsdl_client, $response) = @_; + if ( ! $response ) { + return; + } # copied and adapted from SOAP::WSDL::Client @@ -74,20 +75,16 @@ sub deserialize_message { } # set class resolver if serializer supports it $deserializer->set_class_resolver( $wsdl_client->get_class_resolver() ) - if ( $deserializer->can('set_class_resolver') ); + if $deserializer->can('set_class_resolver'); # Try deserializing response - there may be some, -# even if transport did not succeed (got a 500 response) - if ( ! $response ) { - return; - } - +# even if transport did not succeed (got a 500 response) # as our faults are false, returning a success marker is the only # reliable way of determining whether the deserializer succeeded. # Custom deserializers may return an empty list, or undef, # and $@ is not guaranteed to be undefined. my ($success, $result_body, $result_header) = eval { - (1, $deserializer->deserialize( $response )); + (1, $deserializer->deserialize($response)); }; if ( defined $success ) { return wantarray @@ -110,10 +107,7 @@ sub interpret_messages { my @results; foreach my $response ( @responses ) { - - if ( $verbose ) { - print "Received message:\n" . $response . "\n"; - } + print "Received message:\n" . $response . "\n" if $verbose; my $result = deserialize_message($svc_discover, $response); if ( not $result ) { @@ -151,17 +145,16 @@ sub interpret_messages { foreach my $scope (split ' ', $scopes) { if ( $scope =~ m|onvif://www\.onvif\.org/(.+)/(.*)| ) { my ($attr, $value) = ($1,$2); - if ( 0 < $count ++) { - print ', '; - } + print ', ' if 0 < $count ++; print $attr . '=\'' . $value . '\''; $scopes{$attr} = $value; } } print ")\n"; - push @results, { xaddr=>$xaddr, + push @results, { + xaddr => $xaddr, soap_version => $svc_discover->get_soap_version(), - scopes => \%scopes, + scopes => \%scopes, }; } return @results; @@ -170,7 +163,7 @@ sub interpret_messages { # functions sub discover { - my ( $soap_version, $net_interface ) = @_; + my ($soap_versions, $net_interface) = @_; my @results; ## collect all responses @@ -185,7 +178,7 @@ sub discover { my $uuid_gen = Data::UUID->new(); - foreach my $version ( $soap_version ? ( $soap_version ) : ( '1.1', '1.2') ) { + foreach my $version ( $soap_versions ? ( split(',',$soap_versions) ) : ( '1.1', '1.2') ) { my %services; print "Probing for SOAP $version\n" if $verbose; @@ -195,7 +188,7 @@ sub discover { $svc_discover->set_soap_version($version); if ( $net_interface ) { my $transport = $svc_discover->get_transport(); - print "Setting net interface for $transport to $net_interface\n"; + print "Setting net interface for $transport to $net_interface\n" if $verbose; $transport->set_net_interface($net_interface); } @@ -203,7 +196,15 @@ sub discover { my $result = $svc_discover->ProbeOp( { # WSDiscovery::Types::ProbeType - Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType + ( + ($version eq '1.1') ? + ( + Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType + ) : ( + xmlattr => { 'xmlns:dn' => 'http://www.onvif.org/ver10/network/wsdl', }, + ) + ), + Types => 'dn:NetworkVideoTransmitter', # QNameListType Scopes => { value => '' }, }, WSDiscovery10::Elements::Header->new({ @@ -215,22 +216,23 @@ sub discover { print $result."\n" if $verbose; push @results, interpret_messages($svc_discover, \%services, @responses); + @responses = (); } # end foreach version return @results; } # end sub discover sub profiles { - my ( $client ) = @_; + my ($client) = @_; my $media = $client->get_endpoint('media'); - if ( ! $media ) { + if ( !$media ) { print "No media endpoint for client.\n"; return; } my $result = $media->GetProfiles( { } ,, ); - if ( ! $result ) { + if ( !$result ) { print "No result from GetProfiles.\n"; return; } @@ -244,7 +246,7 @@ sub profiles { print "No profiles returned from get_Profiles\n"; return; } - print "Number of profiles found: " .(scalar @Profiles)."\n" if $verbose; + print 'Number of profiles found: ' .(scalar @Profiles)."\n" if $verbose; my @profiles; foreach my $profile ( @Profiles ) { @@ -339,12 +341,12 @@ sub move { } # end sub move sub metadata { - my ( $client ) = @_; + my ($client) = @_; my $media = $client->get_endpoint('media'); die 'No media endpoint.' if !$media; my $result = $media->GetMetadataConfigurations( { } ,, ); - if ( ! $result ) { + if ( !$result ) { print "No MetaDataConfigurations\n" if $verbose; } else { print $result . "\n"; @@ -363,8 +365,6 @@ sub metadata { } - - 1; __END__ diff --git a/scripts/zmonvif-probe.pl.in b/scripts/zmonvif-probe.pl.in index 3598dfcae..b9d3cd0bf 100644 --- a/scripts/zmonvif-probe.pl.in +++ b/scripts/zmonvif-probe.pl.in @@ -41,7 +41,7 @@ my $OPTIONS = 'v'; sub HELP_MESSAGE { my ($fh, $pkg, $ver, $opts) = @_; - print $fh "Usage: " . __FILE__ . " [-v] probe \n"; + print $fh "Usage: " . __FILE__ . " [-v] probe \n"; print $fh " " . __FILE__ . " [-v] \n"; print $fh <1 } ); $Config{ZM_DB_USER} = $dbUser; $Config{ZM_DB_PASS} = $dbPass; +# we escape dbpass with single quotes so that $ in the password has no effect, but dbpass could have a ' in it. +$dbPass =~ s/'/\\'/g; if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) { if ( $Config{ZM_DYN_DB_VERSION} ) { @@ -384,21 +386,22 @@ if ( $version ) { my $command = 'mysqldump'; if ( defined($portOrSocket) ) { if ( $portOrSocket =~ /^\// ) { - $command .= " -S".$portOrSocket; + $command .= ' -S'.$portOrSocket; } else { - $command .= " -h".$host." -P".$portOrSocket; + $command .= ' -h'.$host.' -P'.$portOrSocket; } } else { - $command .= " -h".$host; + $command .= ' -h'.$host; } if ( $dbUser ) { $command .= ' -u'.$dbUser; - $command .= ' -p"'.$dbPass.'"' if $dbPass; + $command .= ' -p\''.$dbPass.'\'' if $dbPass; } - my $backup = "@ZM_TMPDIR@/".$Config{ZM_DB_NAME}."-".$version.".dump"; - $command .= " --add-drop-table --databases ".$Config{ZM_DB_NAME}." > ".$backup; - print( "Creating backup to $backup. This may take several minutes.\n" ); - print( "Executing '$command'\n" ) if ( logDebugging() ); + my $backup = '@ZM_TMPDIR@/'.$Config{ZM_DB_NAME}.'-'.$version.'.dump'; + $command .= ' --add-drop-table --databases '.$Config{ZM_DB_NAME}.' > '.$backup; + print("Creating backup to $backup. This may take several minutes.\n"); + print("Executing '$command'\n") if logDebugging(); + ($command) = $command =~ /(.*)/; # detaint my $output = qx($command); my $status = $? >> 8; if ( $status || logDebugging() ) { @@ -982,7 +985,7 @@ sub patchDB { } if ( $dbUser ) { $command .= ' -u'.$dbUser; - $command .= ' -p"'.$dbPass.'"' if $dbPass; + $command .= ' -p\''.$dbPass.'\'' if $dbPass; } $command .= ' '.$Config{ZM_DB_NAME}.' < '; if ( $updateDir ) { @@ -993,6 +996,7 @@ sub patchDB { $command .= '/zm_update-'.$version.'.sql'; print("Executing '$command'\n") if logDebugging(); + ($command) = $command =~ /(.*)/; # detaint my $output = qx($command); my $status = $? >> 8; if ( $status || logDebugging() ) { diff --git a/src/zm_db.cpp b/src/zm_db.cpp index 8e6258b0b..35982ce50 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -81,10 +81,11 @@ bool zmDbConnect() { void zmDbClose() { if ( zmDbConnected ) { db_mutex.lock(); - mysql_close( &dbconn ); + mysql_close(&dbconn); // mysql_init() call implicitly mysql_library_init() but // mysql_close() does not call mysql_library_end() - mysql_library_end(); + // We get segfaults and a hang when we call this. So just don't. + //mysql_library_end(); zmDbConnected = false; db_mutex.unlock(); } @@ -96,6 +97,12 @@ MYSQL_RES * zmDbFetch(const char * query) { return NULL; } db_mutex.lock(); + // Might have been disconnected while we waited for the lock + if ( !zmDbConnected ) { + db_mutex.unlock(); + Error("Not connected."); + return NULL; + } if ( mysql_query(&dbconn, query) ) { db_mutex.unlock(); diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index c65bf7445..3bcce223e 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -714,11 +714,9 @@ bool EventStream::sendFrame(int delta_us) { Image *image = NULL; if ( filepath[0] ) { -Debug(1, "Loading image"); image = new Image(filepath); } else if ( ffmpeg_input ) { // Get the frame from the mp4 input - Debug(1,"Getting frame from ffmpeg"); FrameData *frame_data = &event_data->frames[curr_frame_id-1]; AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id(), @@ -767,7 +765,11 @@ Debug(1, "Loading image"); switch ( type ) { case STREAM_JPEG : - send_image->EncodeJpeg(img_buffer, &img_buffer_size); + if ( send_image->EncodeJpeg(img_buffer, &img_buffer_size) ) { + Debug(1, "encoded JPEG"); + } else { + // Failed + } break; case STREAM_ZIP : #if HAVE_ZLIB_H @@ -787,10 +789,6 @@ Debug(1, "Loading image"); Fatal("Unexpected frame type %d", type); break; } - if ( send_image != image ) { - delete send_image; - send_image = NULL; - } delete image; image = NULL; } // end if send_raw or not @@ -815,7 +813,7 @@ Debug(1, "Loading image"); fprintf(stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size); if ( zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size ) { /* sendfile() failed, use standard way instead */ - img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); + img_buffer_size = fread(img_buffer, 1, sizeof(temp_img_buffer), fdj); if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) { fclose(fdj); /* Close the file handle */ Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno)); diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 109be4083..11c25addc 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -975,10 +975,12 @@ int FfmpegCamera::CaptureAndRecord( Error("Error count over 100, going to close and re-open stream"); return -1; } +#if HAVE_LIBAVUTIL_HWCONTEXT_H if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) { use_hwaccel = false; return -1; } +#endif } zm_av_packet_unref(&packet); continue; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 31c71037f..02cdd1ad8 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -1905,11 +1905,11 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour /* RGB32 compatible: complete */ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour ) { - strncpy( text, p_text, sizeof(text)-1 ); + strncpy(text, p_text, sizeof(text)-1); unsigned int index = 0; unsigned int line_no = 0; - unsigned int text_len = strlen( text ); + unsigned int text_len = strlen(text); unsigned int line_len = 0; const char *line = text; @@ -1928,10 +1928,10 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int const bool bg_trans = (bg_colour == RGB_TRANSPARENT); int zm_text_bitmask = 0x80; - if (size == 2) + if ( size == 2 ) zm_text_bitmask = 0x8000; - while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) { + while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) { unsigned int line_width = line_len * ZM_CHAR_WIDTH * size; @@ -1967,10 +1967,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int unsigned char *temp_ptr = ptr; for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; - if (size == 2) + if ( size == 2 ) { + if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; - else + } else { + if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; + } for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) { if ( f & (zm_text_bitmask >> i) ) { if ( !fg_trans ) @@ -1989,10 +1998,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int unsigned char *temp_ptr = ptr; for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; - if (size == 2) + if ( size == 2 ) { + if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; - else + } else { + if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; + } for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) { if ( f & (zm_text_bitmask >> i) ) { if ( !fg_trans ) { @@ -2016,10 +2034,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int Rgb* temp_ptr = (Rgb*)ptr; for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; - if (size == 2) + if ( size == 2 ) { + if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; - else + } else { + if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) { + Warning("Unsupported character %c in %s", line[c], line); + continue; + } f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; + } for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) { if ( f & (zm_text_bitmask >> i) ) { if ( !fg_trans ) { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index ec5e9ac97..d995d4f06 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -552,14 +552,18 @@ bool Monitor::connect() { snprintf(mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id); map_fd = open(mem_file, O_RDWR|O_CREAT, (mode_t)0600); if ( map_fd < 0 ) { - Fatal("Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno)); + Error("Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno)); + return false; } else { Debug(3, "Success opening mmap file at (%s)", mem_file); } struct stat map_stat; - if ( fstat(map_fd, &map_stat) < 0 ) - Fatal("Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno)); + if ( fstat(map_fd, &map_stat) < 0 ) { + Error("Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno)); + close(map_fd); + return false; + } if ( map_stat.st_size != mem_size ) { if ( purpose == CAPTURE ) { diff --git a/src/zmu.cpp b/src/zmu.cpp index 12f8f9338..412bc816c 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -196,12 +196,11 @@ bool ValidateAccess(User *user, int mon_id, int function) { return allowed; } -int exit_zmu(int exit_code) { +void exit_zmu(int exit_code) { logTerm(); zmDbClose(); exit(exit_code); - return exit_code; } int main(int argc, char *argv[]) { @@ -477,228 +476,233 @@ int main(int argc, char *argv[]) { if ( mon_id > 0 ) { Monitor *monitor = Monitor::Load(mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY); - if ( monitor ) { - if ( verbose ) { - printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name()); - } - if ( !monitor->connect() ) { - Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name()); - exit_zmu(-1); - } + if ( !monitor ) { + Error("Unable to load monitor %d", mon_id); + exit_zmu(-1); + } // end if ! MONITOR - char separator = ' '; - bool have_output = false; - if ( function & ZMU_STATE ) { - Monitor::State state = monitor->GetState(); - if ( verbose ) { - printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle")); - } else { - if ( have_output ) fputc(separator, stdout); - printf("%d", state); - have_output = true; - } - } - if ( function & ZMU_TIME ) { - struct timeval timestamp = monitor->GetTimestamp(image_idx); - if ( verbose ) { - char timestamp_str[64] = "None"; - if ( timestamp.tv_sec ) - strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime(×tamp.tv_sec)); - if ( image_idx == -1 ) - printf("Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000); - else - printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000); - } else { - if ( have_output ) fputc(separator, stdout); - printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000); - have_output = true; - } - } - if ( function & ZMU_READ_IDX ) { - if ( verbose ) - printf("Last read index: %d\n", monitor->GetLastReadIndex()); - else { - if ( have_output ) fputc(separator, stdout); - printf("%d", monitor->GetLastReadIndex()); - have_output = true; - } - } - if ( function & ZMU_WRITE_IDX ) { - if ( verbose ) { - printf("Last write index: %d\n", monitor->GetLastWriteIndex()); - } else { - if ( have_output ) fputc(separator, stdout); - printf("%d", monitor->GetLastWriteIndex()); - have_output = true; - } - } - if ( function & ZMU_EVENT ) { - if ( verbose ) { - printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId()); - } else { - if ( have_output ) fputc(separator, stdout); - printf("%" PRIu64, monitor->GetLastEventId()); - have_output = true; - } - } - if ( function & ZMU_FPS ) { - if ( verbose ) { - printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS()); - } else { - if ( have_output ) fputc(separator, stdout); - printf("%.2f", monitor->GetFPS()); - have_output = true; - } - } - if ( function & ZMU_IMAGE ) { - if ( verbose ) { - if ( image_idx == -1 ) - printf("Dumping last image captured to Monitor%d.jpg", monitor->Id()); - else - printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id()); - if ( scale != -1 ) - printf(", scaling by %d%%", scale); - printf("\n"); - } - monitor->GetImage(image_idx, scale>0?scale:100); - } - if ( function & ZMU_ZONES ) { - if ( verbose ) - printf("Dumping zone image to Zones%d.jpg\n", monitor->Id()); - monitor->DumpZoneImage(zoneString); - } - if ( function & ZMU_ALARM ) { - if ( monitor->GetFunction() == Monitor::Function::MONITOR ) { - printf("A Monitor in monitor mode cannot handle alarms. Please use NoDect\n"); - } else { - Monitor::State state = monitor->GetState(); - - if ( verbose ) { - printf("Forcing alarm on current state: %s, event %" PRIu64 "\n", - state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"), - monitor->GetLastEventId() - ); - } - monitor->ForceAlarmOn(config.forced_alarm_score, "Forced Web"); - while ( ((state = monitor->GetState()) != Monitor::ALARM) && !zm_terminate ) { - // Wait for monitor to notice. - usleep(1000); - } - printf("Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId()); - } // end if ! MONITOR - } - if ( function & ZMU_NOALARM ) { - if ( verbose ) - printf("Forcing alarm off\n"); - monitor->ForceAlarmOff(); - } - if ( function & ZMU_CANCEL ) { - if ( verbose ) - printf("Cancelling forced alarm on/off\n"); - monitor->CancelForced(); - } - if ( function & ZMU_RELOAD ) { - if ( verbose ) - printf("Reloading monitor settings\n"); - monitor->actionReload(); - } - if ( function & ZMU_ENABLE ) { - if ( verbose ) - printf("Enabling event generation\n"); - monitor->actionEnable(); - } - if ( function & ZMU_DISABLE ) { - if ( verbose ) - printf("Disabling event generation\n"); - monitor->actionDisable(); - } - if ( function & ZMU_SUSPEND ) { - if ( verbose ) - printf("Suspending event generation\n"); - monitor->actionSuspend(); - } - if ( function & ZMU_RESUME ) { - if ( verbose ) - printf("Resuming event generation\n"); - monitor->actionResume(); - } - if ( function & ZMU_QUERY ) { - char monString[16382] = ""; - monitor->DumpSettings(monString, verbose); - printf("%s\n", monString); - } - if ( function & ZMU_BRIGHTNESS ) { - if ( verbose ) { - if ( brightness >= 0 ) - printf("New brightness: %d\n", monitor->actionBrightness(brightness)); - else - printf("Current brightness: %d\n", monitor->actionBrightness()); - } else { - if ( have_output ) fputc(separator, stdout); - if ( brightness >= 0 ) - printf("%d", monitor->actionBrightness(brightness)); - else - printf("%d", monitor->actionBrightness()); - have_output = true; - } - } - if ( function & ZMU_CONTRAST ) { - if ( verbose ) { - if ( contrast >= 0 ) - printf("New brightness: %d\n", monitor->actionContrast(contrast)); - else - printf("Current contrast: %d\n", monitor->actionContrast()); - } else { - if ( have_output ) fputc(separator, stdout); - if ( contrast >= 0 ) - printf("%d", monitor->actionContrast(contrast)); - else - printf("%d", monitor->actionContrast()); - have_output = true; - } - } - if ( function & ZMU_HUE ) { - if ( verbose ) { - if ( hue >= 0 ) - printf("New hue: %d\n", monitor->actionHue(hue)); - else - printf("Current hue: %d\n", monitor->actionHue()); - } else { - if ( have_output ) fputc(separator, stdout); - if ( hue >= 0 ) - printf("%d", monitor->actionHue(hue)); - else - printf("%d", monitor->actionHue()); - have_output = true; - } - } - if ( function & ZMU_COLOUR ) { - if ( verbose ) { - if ( colour >= 0 ) - printf("New colour: %d\n", monitor->actionColour(colour)); - else - printf("Current colour: %d\n", monitor->actionColour()); - } else { - if ( have_output ) fputc(separator, stdout); - if ( colour >= 0 ) - printf("%d", monitor->actionColour(colour)); - else - printf("%d", monitor->actionColour()); - have_output = true; - } - } - if ( have_output ) { - printf("\n"); - } - if ( !function ) { - Usage(); - } + if ( verbose ) { + printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name()); + } + if ( !monitor->connect() ) { + Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name()); delete monitor; - } else { - Error("Invalid monitor id %d", mon_id); + monitor = NULL; exit_zmu(-1); } - } else { + + char separator = ' '; + bool have_output = false; + if ( function & ZMU_STATE ) { + Monitor::State state = monitor->GetState(); + if ( verbose ) { + printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle")); + } else { + if ( have_output ) fputc(separator, stdout); + printf("%d", state); + have_output = true; + } + } + if ( function & ZMU_TIME ) { + struct timeval timestamp = monitor->GetTimestamp(image_idx); + if ( verbose ) { + char timestamp_str[64] = "None"; + if ( timestamp.tv_sec ) + strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime(×tamp.tv_sec)); + if ( image_idx == -1 ) + printf("Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000); + else + printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000); + } else { + if ( have_output ) fputc(separator, stdout); + printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000); + have_output = true; + } + } + if ( function & ZMU_READ_IDX ) { + if ( verbose ) + printf("Last read index: %d\n", monitor->GetLastReadIndex()); + else { + if ( have_output ) fputc(separator, stdout); + printf("%d", monitor->GetLastReadIndex()); + have_output = true; + } + } + if ( function & ZMU_WRITE_IDX ) { + if ( verbose ) { + printf("Last write index: %d\n", monitor->GetLastWriteIndex()); + } else { + if ( have_output ) fputc(separator, stdout); + printf("%d", monitor->GetLastWriteIndex()); + have_output = true; + } + } + if ( function & ZMU_EVENT ) { + if ( verbose ) { + printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId()); + } else { + if ( have_output ) fputc(separator, stdout); + printf("%" PRIu64, monitor->GetLastEventId()); + have_output = true; + } + } + if ( function & ZMU_FPS ) { + if ( verbose ) { + printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS()); + } else { + if ( have_output ) fputc(separator, stdout); + printf("%.2f", monitor->GetFPS()); + have_output = true; + } + } + if ( function & ZMU_IMAGE ) { + if ( verbose ) { + if ( image_idx == -1 ) + printf("Dumping last image captured to Monitor%d.jpg", monitor->Id()); + else + printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id()); + if ( scale != -1 ) + printf(", scaling by %d%%", scale); + printf("\n"); + } + monitor->GetImage(image_idx, scale>0?scale:100); + } + if ( function & ZMU_ZONES ) { + if ( verbose ) + printf("Dumping zone image to Zones%d.jpg\n", monitor->Id()); + monitor->DumpZoneImage(zoneString); + } + if ( function & ZMU_ALARM ) { + if ( monitor->GetFunction() == Monitor::Function::MONITOR ) { + printf("A Monitor in monitor mode cannot handle alarms. Please use NoDect\n"); + } else { + Monitor::State state = monitor->GetState(); + + if ( verbose ) { + printf("Forcing alarm on current state: %s, event %" PRIu64 "\n", + state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"), + monitor->GetLastEventId() + ); + } + monitor->ForceAlarmOn(config.forced_alarm_score, "Forced Web"); + while ( ((state = monitor->GetState()) != Monitor::ALARM) && !zm_terminate ) { + // Wait for monitor to notice. + usleep(1000); + } + printf("Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId()); + } + } // end if ZMU_ALARM + + if ( function & ZMU_NOALARM ) { + if ( verbose ) + printf("Forcing alarm off\n"); + monitor->ForceAlarmOff(); + } + if ( function & ZMU_CANCEL ) { + if ( verbose ) + printf("Cancelling forced alarm on/off\n"); + monitor->CancelForced(); + } + if ( function & ZMU_RELOAD ) { + if ( verbose ) + printf("Reloading monitor settings\n"); + monitor->actionReload(); + } + if ( function & ZMU_ENABLE ) { + if ( verbose ) + printf("Enabling event generation\n"); + monitor->actionEnable(); + } + if ( function & ZMU_DISABLE ) { + if ( verbose ) + printf("Disabling event generation\n"); + monitor->actionDisable(); + } + if ( function & ZMU_SUSPEND ) { + if ( verbose ) + printf("Suspending event generation\n"); + monitor->actionSuspend(); + } + if ( function & ZMU_RESUME ) { + if ( verbose ) + printf("Resuming event generation\n"); + monitor->actionResume(); + } + if ( function & ZMU_QUERY ) { + char monString[16382] = ""; + monitor->DumpSettings(monString, verbose); + printf("%s\n", monString); + } + if ( function & ZMU_BRIGHTNESS ) { + if ( verbose ) { + if ( brightness >= 0 ) + printf("New brightness: %d\n", monitor->actionBrightness(brightness)); + else + printf("Current brightness: %d\n", monitor->actionBrightness()); + } else { + if ( have_output ) fputc(separator, stdout); + if ( brightness >= 0 ) + printf("%d", monitor->actionBrightness(brightness)); + else + printf("%d", monitor->actionBrightness()); + have_output = true; + } + } + if ( function & ZMU_CONTRAST ) { + if ( verbose ) { + if ( contrast >= 0 ) + printf("New brightness: %d\n", monitor->actionContrast(contrast)); + else + printf("Current contrast: %d\n", monitor->actionContrast()); + } else { + if ( have_output ) fputc(separator, stdout); + if ( contrast >= 0 ) + printf("%d", monitor->actionContrast(contrast)); + else + printf("%d", monitor->actionContrast()); + have_output = true; + } + } + if ( function & ZMU_HUE ) { + if ( verbose ) { + if ( hue >= 0 ) + printf("New hue: %d\n", monitor->actionHue(hue)); + else + printf("Current hue: %d\n", monitor->actionHue()); + } else { + if ( have_output ) fputc(separator, stdout); + if ( hue >= 0 ) + printf("%d", monitor->actionHue(hue)); + else + printf("%d", monitor->actionHue()); + have_output = true; + } + } + if ( function & ZMU_COLOUR ) { + if ( verbose ) { + if ( colour >= 0 ) + printf("New colour: %d\n", monitor->actionColour(colour)); + else + printf("Current colour: %d\n", monitor->actionColour()); + } else { + if ( have_output ) fputc(separator, stdout); + if ( colour >= 0 ) + printf("%d", monitor->actionColour(colour)); + else + printf("%d", monitor->actionColour()); + have_output = true; + } + } + + if ( have_output ) { + printf("\n"); + } + if ( !function ) { + Usage(); + } + delete monitor; + monitor = NULL; + } else { // non monitor functions if ( function & ZMU_QUERY ) { #if ZM_HAS_V4L char vidString[0x10000] = ""; @@ -770,8 +774,9 @@ int main(int argc, char *argv[]) { } // end foreach row mysql_free_result(result); } // end if function && ZMU_LIST - } + } // end if monitor id or not delete user; - return exit_zmu(0); -} + exit_zmu(0); + return 0; +} // end int main() diff --git a/web/ajax/event.php b/web/ajax/event.php index fb9000cc6..1456bd192 100644 --- a/web/ajax/event.php +++ b/web/ajax/event.php @@ -1,5 +1,5 @@ $exportFile,'exportFormat'=>$exportFormat, 'connkey'=>(isset($_REQUEST['connkey'])?$_REQUEST['connkey']:''))); + ajaxResponse(array( + 'exportFile'=>$exportFile, + 'exportFormat'=>$exportFormat, + 'connkey'=>(isset($_REQUEST['connkey'])?$_REQUEST['connkey']:'') + )); } else { ajaxError('Export Failed'); } @@ -145,7 +149,7 @@ if ( canEdit('Events') ) { break; case 'delete' : $Event = new ZM\Event($_REQUEST['id']); - if ( ! $Event->Id() ) { + if ( !$Event->Id() ) { ajaxResponse(array('refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.')); } else { $Event->delete(); diff --git a/web/includes/functions.php b/web/includes/functions.php index f640569c3..d5c98cb3f 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1499,15 +1499,15 @@ function getLoad() { function getDiskPercent($path = ZM_DIR_EVENTS) { $total = disk_total_space($path); if ( $total === false ) { - Error('disk_total_space returned false. Verify the web account user has access to ' . $path); + ZM\Error('disk_total_space returned false. Verify the web account user has access to ' . $path); return 0; } elseif ( $total == 0 ) { - Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path); + ZM\Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path); return 100; } $free = disk_free_space($path); if ( $free === false ) { - Error('disk_free_space returned false. Verify the web account user has access to ' . $path); + ZM\Error('disk_free_space returned false. Verify the web account user has access to ' . $path); } $space = round((($total - $free) / $total) * 100); return $space; @@ -2063,7 +2063,7 @@ function logState() { if ( $count['Level'] <= ZM\Logger::PANIC ) $count['Level'] = ZM\Logger::FATAL; if ( !($levelCount = $levelCounts[$count['Level']]) ) { - Error('Unexpected Log level '.$count['Level']); + ZM\Error('Unexpected Log level '.$count['Level']); next; } if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) { diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 51a4a0820..3d60fde3e 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -423,13 +423,16 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) { if ( count($storage_areas) <= 4 ) echo implode(', ', array_map($func, $storage_areas)); $shm_percent = getDiskPercent(ZM_PATH_MAP); + $shm_total_space = disk_total_space(ZM_PATH_MAP); + $shm_used = $shm_total_space - disk_free_space(ZM_PATH_MAP); + $class = ''; if ( $shm_percent > 98 ) { $class = 'error'; } else if ( $shm_percent > 90 ) { $class = 'warning'; } - echo ' '.ZM_PATH_MAP.': '.$shm_percent.'%'; + echo ' '.ZM_PATH_MAP.': '.$shm_percent.'%'; ?> diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 71c60b6f0..98420783b 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -205,6 +205,7 @@ getBodyTopHTML(); +
@@ -390,9 +391,10 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { - + -
+ +
diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 8b51e0cec..ae14144f5 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -285,7 +285,7 @@ function getCmdResponse( respObj, respText ) { } } // end if haev a new auth hash - streamCmdTimer = streamQuery.delay( streamTimeout ); //Timeout is refresh rate for progressBox and time display + streamCmdTimer = streamQuery.delay(streamTimeout); //Timeout is refresh rate for progressBox and time display } var streamReq = new Request.JSON( { diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index 0a281dd01..56f1ac24a 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -212,7 +212,8 @@ function Monitor(monitorData) { * @param {*} element - the event data passed by onchange callback */ function selectLayout(element) { - layout = $j(element).val(); + var ddm = $j('#zmMontageLayout'); + layout = ddm.val(); if ( layout_id = parseInt(layout) ) { layout = layouts[layout]; @@ -231,6 +232,7 @@ function selectLayout(element) { if ( layout.Positions['default'] ) { styles = layout.Positions['default']; for ( style in styles ) { + console.log("Applying " + style + ' ' + styles[style]); monitor_frame.css(style, styles[style]); } } else { @@ -241,7 +243,6 @@ function selectLayout(element) { styles = layout.Positions['mId'+monitor.id]; for ( style in styles ) { monitor_frame.css(style, styles[style]); - console.log("Applying " + style + ' : ' + styles[style]); } } else { console.log("No Monitor styles to apply"); diff --git a/web/skins/classic/views/js/onvifprobe.js b/web/skins/classic/views/js/onvifprobe.js index 71cb5e16f..4f10e5c29 100644 --- a/web/skins/classic/views/js/onvifprobe.js +++ b/web/skins/classic/views/js/onvifprobe.js @@ -33,3 +33,7 @@ function configureButtons(element) { form.saveBtn.disabled = (form.probe.selectedIndex==0); } } + +function changeInterface(element) { + gotoStep1(element); +} diff --git a/web/skins/classic/views/js/timeline.js b/web/skins/classic/views/js/timeline.js index 8d3f01d4c..8742ac67b 100644 --- a/web/skins/classic/views/js/timeline.js +++ b/web/skins/classic/views/js/timeline.js @@ -36,14 +36,14 @@ function createEventHtml(zm_event, frame) { return eventHtml; } -function showEventDetail( eventHtml ) { - $('instruction').addClass( 'hidden' ); +function showEventDetail(eventHtml) { + $('instruction').addClass('hidden'); $('eventData').empty(); - $('eventData').adopt( eventHtml ); - $('eventData').removeClass( 'hidden' ); + $('eventData').adopt(eventHtml); + $('eventData').removeClass('hidden'); } -function eventDataResponse( respObj, respText ) { +function eventDataResponse(respObj, respText) { var zm_event = respObj.event; if ( !zm_event ) { console.log('Null event'); @@ -179,7 +179,10 @@ function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, dur eventData.addEvent('click', showEvent.pass()); } -function tlZoomBounds( minTime, maxTime ) { +function tlZoomBounds(event) { + var target = event.target; + var minTime = target.getAttribute('data-zoom-min-time'); + var maxTime = target.getAttribute('data-zoom-max-time'); location.replace('?view='+currentView+filterQuery+'&minTime='+minTime+'&maxTime='+maxTime); } @@ -194,14 +197,20 @@ function tlPanRight() { location.replace('?view='+currentView+filterQuery+'&midTime='+maxTime+'&range='+range); } -window.addEventListener("DOMContentLoaded", function() { - document.querySelectorAll("div.event").forEach(function(el) { +window.addEventListener('DOMContentLoaded', function() { + // These look like the code in skin.js, but that code doesn't select for divs. + document.querySelectorAll('div.event').forEach(function(el) { el.onclick = window[el.getAttribute('data-on-click-this')].bind(el, el); el.onmouseover = window[el.getAttribute('data-on-mouseover-this')].bind(el, el); }); - document.querySelectorAll("div.activity").forEach(function(el) { + document.querySelectorAll('div.activity').forEach(function(el) { el.onclick = window[el.getAttribute('data-on-click-this')].bind(el, el); el.onmouseover = window[el.getAttribute('data-on-mouseover-this')].bind(el, el); }); + document.querySelectorAll('div.zoom').forEach(function(el) { + el.onclick = function(ev) { + window[el.getAttribute('data-on-click')](ev); + }; + }); }); diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 8a38afea4..d1af6082d 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -695,12 +695,11 @@ function getControlResponse(respObj, respText) { function controlCmd(event) { button = event.target; control = button.getAttribute('value'); - xtell = button.getAttribute('xtell'); - ytell = button.getAttribute('ytell'); + xtell = button.getAttribute('data-xtell'); + ytell = button.getAttribute('data-ytell'); var locParms = ''; if ( event && (xtell || ytell) ) { - console.log(event); var target = event.target; var coords = $(target).getCoordinates(); @@ -849,7 +848,7 @@ function initPage() { if ( refreshApplet && appletRefreshTime ) { appletRefresh.delay(appletRefreshTime*1000); } - if ( scale == 'auto' ) changeScale(); + if ( scale == '0' || scale == 'auto' ) changeScale(); if ( window.history.length == 1 ) { $j('#closeControl').html(''); } diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index be4df7b16..4e8c2da8d 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -169,12 +169,6 @@ if ( !ZM_PCRE ) // Currently unsupported unset($httpMethods['jpegTags']); -$configTypes = array( - 'None' => translate('None'), - 'ONVIF' => 'ONVIF', - 'PSIA' => 'PSIA', -); - if ( ZM_HAS_V4L1 ) { $v4l1DeviceFormats = array( 'PAL' => 0, @@ -327,31 +321,31 @@ $orientations = array( ); $deinterlaceopts = array( - 'Disabled' => 0x00000000, - 'Four field motion adaptive - Soft' => 0x00001E04, /* 30 change */ - 'Four field motion adaptive - Medium' => 0x00001404, /* 20 change */ - 'Four field motion adaptive - Hard' => 0x00000A04, /* 10 change */ - 'Discard' => 0x00000001, - 'Linear' => 0x00000002, - 'Blend' => 0x00000003, - 'Blend (25%)' => 0x00000205 - ); + 0x00000000 => 'Disabled', + 0x00001E04 => 'Four field motion adaptive - Soft', /* 30 change */ + 0x00001404 => 'Four field motion adaptive - Medium', /* 20 change */ + 0x00000A04 => 'Four field motion adaptive - Hard', /* 10 change */ + 0x00000001 => 'Discard', + 0x00000002 => 'Linear', + 0x00000003 => 'Blend', + 0x00000205 => 'Blend (25%)', +); $deinterlaceopts_v4l2 = array( - 'Disabled' => 0x00000000, - 'Four field motion adaptive - Soft' => 0x00001E04, /* 30 change */ - 'Four field motion adaptive - Medium' => 0x00001404, /* 20 change */ - 'Four field motion adaptive - Hard' => 0x00000A04, /* 10 change */ - 'Discard' => 0x00000001, - 'Linear' => 0x00000002, - 'Blend' => 0x00000003, - 'Blend (25%)' => 0x00000205, - 'V4L2: Capture top field only' => 0x02000000, - 'V4L2: Capture bottom field only' => 0x03000000, - 'V4L2: Alternate fields (Bob)' => 0x07000000, - 'V4L2: Progressive' => 0x01000000, - 'V4L2: Interlaced' => 0x04000000 - ); + 0x00000000 => 'Disabled', + 0x00001E04 => 'Four field motion adaptive - Soft', /* 30 change */ + 0x00001404 => 'Four field motion adaptive - Medium', /* 20 change */ + 0x00000A04 => 'Four field motion adaptive - Hard', /* 10 change */ + 0x00000001 => 'Discard', + 0x00000002 => 'Linear', + 0x00000003 => 'Blend', + 0x00000205 => 'Blend (25%)', + 0x02000000 => 'V4L2: Capture top field only', + 0x03000000 => 'V4L2: Capture bottom field only', + 0x07000000 => 'V4L2: Alternate fields (Bob)', + 0x01000000 => 'V4L2: Progressive', + 0x04000000 => 'V4L2: Interlaced', +); $fastblendopts = array( 'No blending' => 0, @@ -419,7 +413,7 @@ if ( canEdit('Monitors') ) { $tabs = array(); $tabs['general'] = translate('General'); $tabs['source'] = translate('Source'); -$tabs["config"] = translate('MetaConfig'); +$tabs['onvif'] = translate('ONVIF'); if ( $monitor->Type() != 'WebSite' ) { $tabs['storage'] = translate('Storage'); $tabs['timestamp'] = translate('Timestamp'); @@ -498,7 +492,7 @@ if ( ZM_HAS_V4L && ($tab != 'source' || $monitor->Type() != 'Local') ) { if ( $tab != 'onvif' ) { ?> - + '; - echo 'Triggers()) && in_array($optTrigger, $monitor->Triggers()) ) ? ' checked="checked"' : ''). '/> '. $optTrigger; + echo 'Triggers()) && in_array($optTrigger, $monitor->Triggers()) ) ? ' checked="checked"' : ''). '/> '. $optTrigger; $optCount ++; } # end foreach trigger option if ( !$optCount ) { @@ -761,7 +755,7 @@ switch ( $tab ) { case 'onvif' : { ?> - + @@ -835,7 +829,7 @@ include('_monitor_source_nvsocket.php'); -Type() == 'Remote' ) { ?> Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?> @@ -844,7 +838,7 @@ include('_monitor_source_nvsocket.php'); -Protocol() || $monitor->Protocol() == 'http' ) { echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method() ); } else { @@ -1112,7 +1106,7 @@ include('_monitor_source_nvsocket.php'); - ControlId()); + ControlId()); if ( canEdit('Control') ) { echo ' '.makePopupLink('?view=controlcaps', 'zmControlCaps', 'controlcaps', translate('Edit')); } @@ -1140,7 +1134,7 @@ if ( canEdit('Control') ) { - translate('None'), '0' => translate('Home'), @@ -1242,7 +1236,7 @@ echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnL      - sync + sync diff --git a/web/skins/classic/views/monitorprobe.php b/web/skins/classic/views/monitorprobe.php index 9cab32b3e..a76c67810 100644 --- a/web/skins/classic/views/monitorprobe.php +++ b/web/skins/classic/views/monitorprobe.php @@ -39,16 +39,18 @@ function probeV4L() { } $monitors = array(); - foreach ( dbFetchAll("SELECT Id, Name, Device,Channel FROM Monitors WHERE Type = 'Local' ORDER BY Device, Channel" ) as $monitor ) + foreach ( dbFetchAll("SELECT Id, Name, Device, Channel FROM Monitors WHERE Type = 'Local' ORDER BY Device, Channel" ) as $monitor ) $monitors[$monitor['Device'].':'.$monitor['Channel']] = $monitor; $devices = array(); $preferredStandards = array('PAL', 'NTSC'); $preferredFormats = array('BGR3', 'RGB3', 'YUYV', 'UYVY', 'JPEG', 'MJPG', '422P', 'YU12', 'GREY'); foreach ( $output as $line ) { - if ( !preg_match('/^d:([^|]+).*S:([^|]*).*F:([^|]+).*I:(\d+)\|(.+)$/', $line, $deviceMatches) ) - ZM\Fatal("Can't parse command output '$line'"); - $standards = explode('/',$deviceMatches[2]); + if ( !preg_match('/^d:([^|]+).*S:([^|]*).*F:([^|]+).*I:(\d+)\|(.+)$/', $line, $deviceMatches) ) { + ZM\Error("Can't parse command output '$line'"); + continue; + } + $standards = explode('/', $deviceMatches[2]); $preferredStandard = false; foreach ( $preferredStandards as $standard ) { if ( in_array( $standard, $standards ) ) { @@ -56,7 +58,7 @@ function probeV4L() { break; } } - $formats = explode('/',$deviceMatches[3]); + $formats = explode('/', $deviceMatches[3]); $preferredFormat = false; foreach ( $preferredFormats as $format ) { if ( in_array($format, $formats) ) { @@ -73,8 +75,10 @@ function probeV4L() { ); $inputs = array(); for ( $i = 0; $i < $deviceMatches[4]; $i++ ) { - if ( !preg_match('/i'.$i.':([^|]+)\|i'.$i.'T:([^|]+)\|/', $deviceMatches[5], $inputMatches) ) - ZM\Fatal("Can't parse input '".$deviceMatches[5]."'"); + if ( !preg_match('/i'.$i.':([^|]+)\|i'.$i.'T:([^|]+)\|/', $deviceMatches[5], $inputMatches) ) { + ZM\Error("Can't parse input '".$deviceMatches[5]."'"); + continue; + } if ( $inputMatches[2] == 'Camera' ) { $input = array( 'index' => $i, @@ -101,7 +105,7 @@ function probeV4L() { $inputMonitor['Colours'] = 1; $inputMonitor['SignalCheckColour'] = '#000023'; } - $inputDesc = base64_encode(serialize($inputMonitor)); + $inputDesc = base64_encode(json_encode($inputMonitor)); $inputString = $deviceMatches[1].', chan '.$i.($input['free']?(' - '.translate('Available')):(' ('.$monitors[$input['id']]['Name'].')')); $inputs[] = $input; $cameras[$inputDesc] = $inputString; @@ -288,7 +292,7 @@ function probeNetwork() { if ( isset($macBases[$macRoot]) ) { $macBase = $macBases[$macRoot]; $camera = call_user_func($macBase['probeFunc'], $ip); - $sourceDesc = base64_encode(serialize($camera['monitor'])); + $sourceDesc = base64_encode(json_encode($camera['monitor'])); $sourceString = $camera['model'].' @ '.$host; if ( isset($monitors[$ip]) ) { $monitor = $monitors[$ip]; @@ -330,7 +334,7 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );

- + 'configureButtons(this)')); ?>

diff --git a/web/skins/classic/views/onvifprobe.php b/web/skins/classic/views/onvifprobe.php index ef4e3523d..95e1abeba 100644 --- a/web/skins/classic/views/onvifprobe.php +++ b/web/skins/classic/views/onvifprobe.php @@ -29,16 +29,17 @@ $cameras[0] = translate('ChooseDetectedCamera'); $profiles = array(); $profiles[0] = translate('ChooseDetectedProfile'); -function execONVIF( $cmd ) { +function execONVIF($cmd) { $shell_command = escapeshellcmd(ZM_PATH_BIN . "/zmonvif-probe.pl $cmd"); - exec( $shell_command, $output, $status ); + exec($shell_command, $output, $status); if ( $status ) { - $html_output = implode( '
', $output ); - ZM\Fatal( "Unable to probe network cameras, status is '$status'. Output was:

- $html_output

- Please the following command from a command line for more information:

$shell_command" + $html_output = implode('
', $output); + ZM\Error("Unable to probe network cameras, status is '$status'. Output was: + $html_output + Please run the following command from a command line for more information: + $shell_command" ); } else { ZM\Logger::Debug('Results from probe: '.implode('
', $output)); @@ -49,7 +50,8 @@ function execONVIF( $cmd ) { function probeCameras($localIp) { $cameras = array(); - if ( $lines = @execONVIF('probe') ) { + $lines = @execONVIF('probe 1.1,1.2'.(isset($_REQUEST['interface']) ? ' '.isset($_REQUEST['interface']) : '' )); + if ( $lines ) { foreach ( $lines as $line ) { $line = rtrim($line); if ( preg_match('|^(.+),(.+),\s\((.*)\)$|', $line, $matches) ) { @@ -62,20 +64,23 @@ function probeCameras($localIp) { 'Type' => 'Ffmpeg', 'Host' => $device_ep, 'SOAP' => $soapversion, - 'ConfigURL' => $device_ep, - 'ConfigOptions' => 'SOAP' . $soapversion, + 'ConfigURL' => $device_ep, + 'ConfigOptions' => 'SOAP' . $soapversion, + 'Notes' => '', ), ); foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) { if ( preg_match('|(.+)=\'(.*)\'|', $attr_val, $tokens) ) { if ( $tokens[1] == 'hardware' ) { $camera['model'] = $tokens[2]; - } elseif ( $tokens[1] == 'name' ) { + } else if ( $tokens[1] == 'name' ) { $camera['monitor']['Name'] = $tokens[2]; - } elseif ( $tokens[1] == 'location' ) { - // $camera['location'] = $tokens[2]; + } else if ( $tokens[1] == 'type' ) { + } else if ( $tokens[1] == 'location' or $tokens[1] == 'location/city' or $tokens[1] == 'location/country' ) { + $camera['monitor']['Notes'] .= $tokens[1].'='.$tokens[2]."\n"; + // $camera['location'] = $tokens[2]; } else { - ZM\Logger::Debug('Unknown token ' . $tokens[1]); + ZM\Logger::Debug('Unknown token '.$tokens[1].' = '.$tokens[2]); } } } // end foreach token @@ -165,6 +170,48 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {

+

+ ', $output); + ZM\Error("Unable to list network interfaces, status is '$status'. Output was:

$html_output"); + } else { + foreach ( $output as $line ) { + if ( preg_match('/^\d+: ([[:alnum:]]+):/', $line, $matches ) ) { + if ( $matches[1] != 'lo' ) { + $interfaces[$matches[1]] = $matches[1]; + } else { + ZM\Logger::Debug("No match for $line"); + } + } + } + } + $routes = array(); + exec('ip route', $output, $status); + if ( $status ) { + $html_output = implode('
', $output); + ZM\Error("Unable to list network interfaces, status is '$status'. Output was:

$html_output"); + } else { + foreach ( $output as $line ) { + if ( preg_match('/^default via [.[:digit:]]+ dev ([[:alnum:]]+)/', $line, $matches) ) { + $default_interface = $matches[1]; + } else if ( preg_match('/^([.\/[:digit:]]+) dev ([[:alnum:]]+)/', $line, $matches) ) { + $interfaces[$matches[2]] .= ' ' . $matches[1]; + } + } # end foreach line of output + } + + echo htmlSelect('interface', $interfaces, + (isset($_REQUEST['interface']) ? $_REQUEST['interface'] : $default_interface), + array('data-on-change-this'=>'changeInterface') ); + +?> +

+

'configureButtons')); ?> @@ -180,6 +227,7 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {

+
diff --git a/web/skins/classic/views/timeline.php b/web/skins/classic/views/timeline.php index 794b99c20..cab313f52 100644 --- a/web/skins/classic/views/timeline.php +++ b/web/skins/classic/views/timeline.php @@ -154,7 +154,7 @@ if ( isset($_REQUEST['midTime']) ) if ( isset($_REQUEST['maxTime']) ) $maxTime = validHtmlStr($_REQUEST['maxTime']); -if ( isset($range) ) { +if ( isset($range) and validInt($range) ) { $halfRange = (int)($range/2); if ( isset($midTime) ) { $midTimeT = strtotime($midTime); @@ -616,7 +616,7 @@ function drawXGrid( $chart, $scale, $labelClass, $tickClass, $gridClass, $zoomCl $zoomMinTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($lastTick * $chart['data']['x']['density'])) ); $zoomMaxTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density'])) ); ?> -
+
-
+