Merge branch 'master' of github.com:ZoneMinder/zoneminder
This commit is contained in:
commit
b7cc5dde54
|
@ -148,6 +148,9 @@ set(ZM_CACHEDIR "/var/cache/zoneminder" CACHE PATH
|
||||||
"Location of the web server cache busting files, default: /var/cache/zoneminder")
|
"Location of the web server cache busting files, default: /var/cache/zoneminder")
|
||||||
set(ZM_CONTENTDIR "/var/lib/zoneminder" CACHE PATH
|
set(ZM_CONTENTDIR "/var/lib/zoneminder" CACHE PATH
|
||||||
"Location of dynamic content (events and images), default: /var/lib/zoneminder")
|
"Location of dynamic content (events and images), default: /var/lib/zoneminder")
|
||||||
|
set(ZM_FONTDIR "${CMAKE_INSTALL_FULL_DATADIR}/zoneminder/fonts" CACHE PATH
|
||||||
|
"Location of the font files used for timestamping, default: <prefix>/${CMAKE_INSTALL_DATADIR}/zoneminder/fonts")
|
||||||
|
|
||||||
set(ZM_DB_HOST "localhost" CACHE STRING
|
set(ZM_DB_HOST "localhost" CACHE STRING
|
||||||
"Hostname where ZoneMinder database located, default: localhost")
|
"Hostname where ZoneMinder database located, default: localhost")
|
||||||
set(ZM_DB_NAME "zm" CACHE STRING
|
set(ZM_DB_NAME "zm" CACHE STRING
|
||||||
|
@ -911,6 +914,7 @@ set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(scripts)
|
add_subdirectory(scripts)
|
||||||
add_subdirectory(db)
|
add_subdirectory(db)
|
||||||
|
add_subdirectory(fonts)
|
||||||
add_subdirectory(web)
|
add_subdirectory(web)
|
||||||
add_subdirectory(misc)
|
add_subdirectory(misc)
|
||||||
add_subdirectory(onvif)
|
add_subdirectory(onvif)
|
||||||
|
|
|
@ -337,6 +337,7 @@ CREATE TABLE `Groups` (
|
||||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||||
`Name` varchar(64) NOT NULL default '',
|
`Name` varchar(64) NOT NULL default '',
|
||||||
`ParentId` int(10) unsigned,
|
`ParentId` int(10) unsigned,
|
||||||
|
FOREIGN KEY (`ParentId`) REFERENCES `Groups` (`Id`) ON DELETE CASCADE,
|
||||||
PRIMARY KEY (`Id`)
|
PRIMARY KEY (`Id`)
|
||||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||||
|
|
||||||
|
@ -348,7 +349,9 @@ DROP TABLE IF EXISTS `Groups_Monitors`;
|
||||||
CREATE TABLE `Groups_Monitors` (
|
CREATE TABLE `Groups_Monitors` (
|
||||||
`Id` INT(10) unsigned NOT NULL auto_increment,
|
`Id` INT(10) unsigned NOT NULL auto_increment,
|
||||||
`GroupId` int(10) unsigned NOT NULL,
|
`GroupId` int(10) unsigned NOT NULL,
|
||||||
|
FOREIGN KEY (`GroupId`) REFERENCES `Groups` (`Id`) ON DELETE CASCADE,
|
||||||
`MonitorId` int(10) unsigned NOT NULL,
|
`MonitorId` int(10) unsigned NOT NULL,
|
||||||
|
FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE,
|
||||||
PRIMARY KEY (`Id`)
|
PRIMARY KEY (`Id`)
|
||||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||||
|
|
||||||
|
@ -447,6 +450,7 @@ CREATE TABLE `Monitors` (
|
||||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||||
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||||
|
`DecodingEnabled` tinyint(3) unsigned NOT NULL default '1',
|
||||||
`LinkedMonitors` varchar(255),
|
`LinkedMonitors` varchar(255),
|
||||||
`Triggers` set('X10') NOT NULL default '',
|
`Triggers` set('X10') NOT NULL default '',
|
||||||
`ONVIF_URL` VARCHAR(255) NOT NULL DEFAULT '',
|
`ONVIF_URL` VARCHAR(255) NOT NULL DEFAULT '',
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
Add the EndTime IS NOT NULL term to the Update Disk Space Filter.
|
||||||
|
This will only work if they havn't modified the stock filter
|
||||||
|
*/
|
||||||
|
UPDATE Filters SET Query_json='{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}]}' WHERE Query_json='{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the EndTime IS NOT NULL term to the Purge When Full Filter.
|
||||||
|
This will only work if they havn't modified the stock filter .
|
||||||
|
This is important to prevent SQL Errors inserting into Frames table if PurgeWhenFull deletes in-progress events.
|
||||||
|
*/
|
||||||
|
UPDATE Filters SET Query_json='{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}],"limit":100,"sort_asc":1}' WHERE Query_json='{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}';
|
||||||
|
|
||||||
|
/* Add FOREIGN KEYS After deleting lost records */
|
||||||
|
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Groups_Monitors' and column_name='GroupId' and referenced_table_name='Groups' and referenced_column_name='Id');
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
|
||||||
|
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY GroupId in Groups_Monitors already exists'", @sqlstmt);
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for GroupId to Groups_Monitors'", @sqlstmt);
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Groups_Monitors'", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "DELETE FROM `Groups_Monitors` WHERE `GroupId` NOT IN (SELECT `Id` FROM `Groups`)", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "ALTER TABLE `Groups_Monitors` ADD FOREIGN KEY (`GroupId`) REFERENCES `Groups` (`Id`) ON DELETE CASCADE", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
/* Add FOREIGN KEYS After deleting lost records */
|
||||||
|
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Groups_Monitors' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id');
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
|
||||||
|
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY MonitorId in Groups_Monitors already exists'", @sqlstmt);
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for MonitorId to Groups_Monitors'", @sqlstmt);
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Groups_Monitors'", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "DELETE FROM `Groups_Monitors` WHERE `MonitorId` NOT IN (SELECT `Id` FROM `Monitors`)", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "ALTER TABLE `Groups_Monitors` ADD FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
/* Add FOREIGN KEYS After deleting lost records */
|
||||||
|
set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Groups' and column_name='ParentId' and referenced_table_name='Groups' and referenced_column_name='Id');
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'");
|
||||||
|
set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY ParentId in Groups already exists'", @sqlstmt);
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for ParentId to Groups'", @sqlstmt);
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Groups'", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "UPDATE `Groups` SET `ParentId` = NULL WHERE (ParentId IS NOT NULL) and ParentId NOT IN (SELECT * FROM(SELECT Id FROM `Groups`)tblTmp)", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
set @sqlstmt := if( @exist = 0, "ALTER TABLE `Groups` ADD FOREIGN KEY (ParentId) REFERENCES `Groups` (Id) ON DELETE CASCADE", "SELECT '.'");
|
||||||
|
PREPARE stmt FROM @sqlstmt;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'Monitors'
|
||||||
|
AND column_name = 'DecodingEnabled'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column DecodingEnabled already exists in Monitors'",
|
||||||
|
"ALTER TABLE Monitors ADD `DecodingEnabled` tinyint(3) unsigned NOT NULL default '1' AFTER `Enabled`"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
|
@ -28,7 +28,7 @@
|
||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
|
|
||||||
Name: zoneminder
|
Name: zoneminder
|
||||||
Version: 1.35.14
|
Version: 1.35.16
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A camera monitoring and analysis tool
|
Summary: A camera monitoring and analysis tool
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|
|
@ -5,5 +5,6 @@ var/cache/zoneminder/images
|
||||||
var/cache/zoneminder/temp
|
var/cache/zoneminder/temp
|
||||||
var/cache/zoneminder/cache
|
var/cache/zoneminder/cache
|
||||||
usr/share/zoneminder/db
|
usr/share/zoneminder/db
|
||||||
|
usr/share/zoneminder/fonts
|
||||||
etc/zm/
|
etc/zm/
|
||||||
etc/zm/conf.d
|
etc/zm/conf.d
|
||||||
|
|
|
@ -5,6 +5,7 @@ usr/lib/zoneminder
|
||||||
usr/share/polkit-1
|
usr/share/polkit-1
|
||||||
usr/share/zoneminder/db
|
usr/share/zoneminder/db
|
||||||
usr/share/zoneminder/www
|
usr/share/zoneminder/www
|
||||||
|
usr/share/zoneminder/fonts
|
||||||
|
|
||||||
# libzoneminder-perl files:
|
# libzoneminder-perl files:
|
||||||
usr/share/man/man3
|
usr/share/man/man3
|
||||||
|
|
|
@ -5,5 +5,6 @@ var/cache/zoneminder/images
|
||||||
var/cache/zoneminder/temp
|
var/cache/zoneminder/temp
|
||||||
var/cache/zoneminder/cache
|
var/cache/zoneminder/cache
|
||||||
usr/share/zoneminder/db
|
usr/share/zoneminder/db
|
||||||
|
usr/share/zoneminder/fonts
|
||||||
etc/zm/
|
etc/zm/
|
||||||
etc/zm/conf.d
|
etc/zm/conf.d
|
||||||
|
|
|
@ -5,6 +5,7 @@ usr/lib/zoneminder
|
||||||
usr/share/polkit-1
|
usr/share/polkit-1
|
||||||
usr/share/zoneminder/db
|
usr/share/zoneminder/db
|
||||||
usr/share/zoneminder/www
|
usr/share/zoneminder/www
|
||||||
|
usr/share/zoneminder/fonts
|
||||||
|
|
||||||
# libzoneminder-perl files:
|
# libzoneminder-perl files:
|
||||||
usr/share/man/man3
|
usr/share/man/man3
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Glob all database upgrade scripts
|
||||||
|
file(GLOB fontfileslist RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.zmfnt")
|
||||||
|
# Install the fonts
|
||||||
|
install(FILES ${fontfileslist} DESTINATION "${ZM_FONTDIR}")
|
||||||
|
|
Binary file not shown.
|
@ -3780,6 +3780,14 @@ our @options = (
|
||||||
type => $types{boolean},
|
type => $types{boolean},
|
||||||
category => 'logging',
|
category => 'logging',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => 'ZM_FONT_FILE_LOCATION',
|
||||||
|
default => '@ZM_FONTDIR@/default.zmfnt',
|
||||||
|
description => 'Font file location',
|
||||||
|
help => 'This font is used for timestamp labels.',
|
||||||
|
type => $types{string},
|
||||||
|
category => 'config',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
||||||
|
|
|
@ -32,6 +32,7 @@ require ZoneMinder::Base;
|
||||||
require ZoneMinder::Object;
|
require ZoneMinder::Object;
|
||||||
require ZoneMinder::Storage;
|
require ZoneMinder::Storage;
|
||||||
require ZoneMinder::Frame;
|
require ZoneMinder::Frame;
|
||||||
|
require ZoneMinder::Monitor;
|
||||||
require Date::Manip;
|
require Date::Manip;
|
||||||
require File::Find;
|
require File::Find;
|
||||||
require File::Path;
|
require File::Path;
|
||||||
|
@ -915,6 +916,15 @@ sub canEdit {
|
||||||
return 0;
|
return 0;
|
||||||
} # end sub canEdit
|
} # end sub canEdit
|
||||||
|
|
||||||
|
sub Monitor {
|
||||||
|
my $self = shift;
|
||||||
|
$$self{Monitor} = shift if @_;
|
||||||
|
if ( !$$self{Monitor} ) {
|
||||||
|
$$self{Monitor} = new ZoneMinder::Monitor($$self{MonitorId});
|
||||||
|
}
|
||||||
|
return $$self{Monitor};
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
|
|
@ -92,11 +92,13 @@ sub Execute {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $self->{HasDiskPercent} ) {
|
if ( $self->{HasDiskPercent} ) {
|
||||||
my $disk_percent = getDiskPercent($$self{Storage} ? $$self{Storage}->Path() : ());
|
$$self{Storage} = ZoneMinder::Storage->find_one() if ! $$self{Storage};
|
||||||
|
my $disk_percent = getDiskPercent($$self{Storage} ? $$self{Storage}->Path() : $Config{ZM_DIR_EVENTS});
|
||||||
$sql =~ s/zmDiskPercent/$disk_percent/g;
|
$sql =~ s/zmDiskPercent/$disk_percent/g;
|
||||||
}
|
}
|
||||||
if ( $self->{HasDiskBlocks} ) {
|
if ( $self->{HasDiskBlocks} ) {
|
||||||
my $disk_blocks = getDiskBlocks();
|
$$self{Storage} = ZoneMinder::Storage->find_one() if ! $$self{Storage};
|
||||||
|
my $disk_blocks = getDiskBlocks($$self{Storage} ? $$self{Storage}->Path() : $Config{ZM_DIR_EVENTS});
|
||||||
$sql =~ s/zmDiskBlocks/$disk_blocks/g;
|
$sql =~ s/zmDiskBlocks/$disk_blocks/g;
|
||||||
}
|
}
|
||||||
if ( $self->{HasSystemLoad} ) {
|
if ( $self->{HasSystemLoad} ) {
|
||||||
|
@ -421,7 +423,7 @@ sub getDiskPercent {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getDiskBlocks {
|
sub getDiskBlocks {
|
||||||
my $command = 'df .';
|
my $command = 'df ' . ($_[0] ? $_[0] : '.');
|
||||||
my $df = qx( $command );
|
my $df = qx( $command );
|
||||||
my $space = -1;
|
my $space = -1;
|
||||||
if ( $df =~ /\s(\d+)\s+\d+\s+\d+%/ms ) {
|
if ( $df =~ /\s(\d+)\s+\d+\s+\d+%/ms ) {
|
||||||
|
|
|
@ -381,8 +381,10 @@ sub checkFilter {
|
||||||
} # end if AutoCopy
|
} # end if AutoCopy
|
||||||
|
|
||||||
if ( $filter->{UpdateDiskSpace} ) {
|
if ( $filter->{UpdateDiskSpace} ) {
|
||||||
$ZoneMinder::Database::dbh->begin_work();
|
if ( $$filter{LockRows} ) {
|
||||||
$Event->lock_and_load();
|
$ZoneMinder::Database::dbh->begin_work();
|
||||||
|
$Event->lock_and_load();
|
||||||
|
}
|
||||||
|
|
||||||
my $old_diskspace = $$Event{DiskSpace};
|
my $old_diskspace = $$Event{DiskSpace};
|
||||||
my $new_diskspace = $Event->DiskSpace(undef);
|
my $new_diskspace = $Event->DiskSpace(undef);
|
||||||
|
@ -394,7 +396,7 @@ sub checkFilter {
|
||||||
) {
|
) {
|
||||||
$Event->save();
|
$Event->save();
|
||||||
}
|
}
|
||||||
$ZoneMinder::Database::dbh->commit();
|
$ZoneMinder::Database::dbh->commit() if !$$filter{LockRows};
|
||||||
} # end if UpdateDiskSpace
|
} # end if UpdateDiskSpace
|
||||||
} # end foreach event
|
} # end foreach event
|
||||||
ZoneMinder::Database::end_transaction($dbh, $in_transaction) if $$filter{LockRows};
|
ZoneMinder::Database::end_transaction($dbh, $in_transaction) if $$filter{LockRows};
|
||||||
|
|
|
@ -91,6 +91,9 @@ while( 1 ) {
|
||||||
}
|
}
|
||||||
} # end if ZM_LOG_DATABASE_LIMIT
|
} # end if ZM_LOG_DATABASE_LIMIT
|
||||||
|
|
||||||
|
# Delete any sessions that are more ethan a week old. Limiting to 100 because mysql sucks
|
||||||
|
zmDbDo('DELETE FROM Sessions WHERE access < ? LIMIT 100', time - (60*60*24*7));
|
||||||
|
|
||||||
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
||||||
} # end while (1)
|
} # end while (1)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
configure_file(zm_config_data.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config_data.h" @ONLY)
|
configure_file(zm_config_data.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config_data.h" @ONLY)
|
||||||
|
|
||||||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_font.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||||
|
|
||||||
|
|
||||||
# A fix for cmake recompiling the source files for every target.
|
# A fix for cmake recompiling the source files for every target.
|
||||||
|
|
6155
src/zm_bigfont.h
6155
src/zm_bigfont.h
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// ZoneMinder Event Class Implementation, $Date$, $Revision$
|
// ZoneMinder Event Class Implementation
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
// Copyright (C) 2001-2008 Philip Coombes
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software; you can redistribute it and/or
|
||||||
|
@ -79,7 +79,6 @@ Event::Event(
|
||||||
start_time = now;
|
start_time = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int state_id = 0;
|
unsigned int state_id = 0;
|
||||||
zmDbRow dbrow;
|
zmDbRow dbrow;
|
||||||
if ( dbrow.fetch("SELECT Id FROM States WHERE IsActive=1") ) {
|
if ( dbrow.fetch("SELECT Id FROM States WHERE IsActive=1") ) {
|
||||||
|
@ -356,7 +355,7 @@ bool Event::WriteFrameImage(
|
||||||
bool Event::WriteFrameVideo(
|
bool Event::WriteFrameVideo(
|
||||||
const Image *image,
|
const Image *image,
|
||||||
const struct timeval timestamp,
|
const struct timeval timestamp,
|
||||||
VideoWriter* videow) {
|
VideoWriter* videow) const {
|
||||||
const Image* frameimg = image;
|
const Image* frameimg = image;
|
||||||
Image ts_image;
|
Image ts_image;
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
//
|
//
|
||||||
// ZoneMinder Core Interfaces, $Date$, $Revision$
|
// ZoneMinder Core Interfaces, $Date$, $Revision$
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
// Copyright (C) 2001-2008 Philip Coombes
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License
|
// modify it under the terms of the GNU General Public License
|
||||||
// as published by the Free Software Foundation; either version 2
|
// as published by the Free Software Foundation; either version 2
|
||||||
// of the License, or (at your option) any later version.
|
// of the License, or (at your option) any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef ZM_EVENT_H
|
#ifndef ZM_EVENT_H
|
||||||
#define ZM_EVENT_H
|
#define ZM_EVENT_H
|
||||||
|
@ -45,25 +45,24 @@ class Zone;
|
||||||
class Monitor;
|
class Monitor;
|
||||||
class EventStream;
|
class EventStream;
|
||||||
|
|
||||||
#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored
|
// Maximum number of prealarm frames that can be stored
|
||||||
|
#define MAX_PRE_ALARM_FRAMES 16
|
||||||
typedef uint64_t event_id_t;
|
typedef uint64_t event_id_t;
|
||||||
typedef enum { NORMAL=0, BULK, ALARM } FrameType;
|
typedef enum { NORMAL=0, BULK, ALARM } FrameType;
|
||||||
|
|
||||||
#include "zm_frame.h"
|
#include "zm_frame.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class describing events, i.e. captured periods of activity.
|
// Class describing events, i.e. captured periods of activity.
|
||||||
//
|
//
|
||||||
class Event {
|
class Event {
|
||||||
friend class EventStream;
|
friend class EventStream;
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
static int sd;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef std::set<std::string> StringSet;
|
typedef std::set<std::string> StringSet;
|
||||||
typedef std::map<std::string,StringSet> StringSetMap;
|
typedef std::map<std::string,StringSet> StringSetMap;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const char * frame_type_names[3];
|
static const char * frame_type_names[3];
|
||||||
|
|
||||||
struct PreAlarmData {
|
struct PreAlarmData {
|
||||||
|
@ -103,13 +102,18 @@ class Event {
|
||||||
int last_db_frame;
|
int last_db_frame;
|
||||||
Storage::Schemes scheme;
|
Storage::Schemes scheme;
|
||||||
|
|
||||||
void createNotes( std::string ¬es );
|
void createNotes(std::string ¬es);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool OpenFrameSocket( int );
|
static bool OpenFrameSocket(int);
|
||||||
static bool ValidateFrameSocket( int );
|
static bool ValidateFrameSocket(int);
|
||||||
|
|
||||||
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent=false );
|
Event(
|
||||||
|
Monitor *p_monitor,
|
||||||
|
struct timeval p_start_time,
|
||||||
|
const std::string &p_cause,
|
||||||
|
const StringSetMap &p_noteSetMap,
|
||||||
|
bool p_videoEvent=false);
|
||||||
~Event();
|
~Event();
|
||||||
|
|
||||||
uint64_t Id() const { return id; }
|
uint64_t Id() const { return id; }
|
||||||
|
@ -120,36 +124,54 @@ class Event {
|
||||||
const struct timeval &StartTime() const { return start_time; }
|
const struct timeval &StartTime() const { return start_time; }
|
||||||
const struct timeval &EndTime() const { return end_time; }
|
const struct timeval &EndTime() const { return end_time; }
|
||||||
|
|
||||||
bool SendFrameImage( const Image *image, bool alarm_frame=false );
|
bool SendFrameImage(const Image *image, bool alarm_frame=false);
|
||||||
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ) const;
|
bool WriteFrameImage(
|
||||||
bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow );
|
Image *image,
|
||||||
|
struct timeval timestamp,
|
||||||
|
const char *event_file,
|
||||||
|
bool alarm_frame=false
|
||||||
|
) const;
|
||||||
|
bool WriteFrameVideo(
|
||||||
|
const Image *image,
|
||||||
|
const struct timeval timestamp,
|
||||||
|
VideoWriter* videow
|
||||||
|
) const;
|
||||||
|
|
||||||
void updateNotes( const StringSetMap &stringSetMap );
|
void updateNotes(const StringSetMap &stringSetMap);
|
||||||
|
|
||||||
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
|
void AddFrames(int n_frames, Image **images, struct timeval **timestamps);
|
||||||
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_image=nullptr );
|
void AddFrame(
|
||||||
|
Image *image,
|
||||||
|
struct timeval timestamp,
|
||||||
|
int score=0,
|
||||||
|
Image *alarm_image=nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
|
void AddFramesInternal(
|
||||||
|
int n_frames,
|
||||||
|
int start_frame,
|
||||||
|
Image **images,
|
||||||
|
struct timeval **timestamps);
|
||||||
void WriteDbFrames();
|
void WriteDbFrames();
|
||||||
void UpdateFramesDelta(double offset);
|
void UpdateFramesDelta(double offset);
|
||||||
bool SetPath(Storage *storage);
|
bool SetPath(Storage *storage);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const char *getSubPath( struct tm *time ) {
|
static const char *getSubPath(struct tm *time) {
|
||||||
static char subpath[PATH_MAX] = "";
|
static char subpath[PATH_MAX] = "";
|
||||||
snprintf(subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec);
|
snprintf(subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d",
|
||||||
|
time->tm_year-100, time->tm_mon+1, time->tm_mday,
|
||||||
|
time->tm_hour, time->tm_min, time->tm_sec);
|
||||||
return subpath;
|
return subpath;
|
||||||
}
|
}
|
||||||
static const char *getSubPath( time_t *time ) {
|
static const char *getSubPath(time_t *time) {
|
||||||
return Event::getSubPath( localtime( time ) );
|
return Event::getSubPath(localtime(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getEventFile(void) const {
|
const char* getEventFile(void) const {
|
||||||
return video_file.c_str();
|
return video_file.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
static int PreAlarmCount() {
|
static int PreAlarmCount() {
|
||||||
return pre_alarm_count;
|
return pre_alarm_count;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +188,12 @@ class Event {
|
||||||
}
|
}
|
||||||
pre_alarm_count = 0;
|
pre_alarm_count = 0;
|
||||||
}
|
}
|
||||||
static void AddPreAlarmFrame(Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=nullptr) {
|
static void AddPreAlarmFrame(
|
||||||
|
Image *image,
|
||||||
|
struct timeval timestamp,
|
||||||
|
int score=0,
|
||||||
|
Image *alarm_frame=nullptr
|
||||||
|
) {
|
||||||
pre_alarm_data[pre_alarm_count].image = new Image(*image);
|
pre_alarm_data[pre_alarm_count].image = new Image(*image);
|
||||||
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
|
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
|
||||||
pre_alarm_data[pre_alarm_count].score = score;
|
pre_alarm_data[pre_alarm_count].score = score;
|
||||||
|
|
|
@ -883,7 +883,7 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
AVPacket *avp = queued_packet->av_packet();
|
AVPacket *avp = queued_packet->av_packet();
|
||||||
|
|
||||||
// compute time offset between event start and first frame in video
|
// compute time offset between event start and first frame in video
|
||||||
if (packet_count == 0){
|
if ( packet_count == 0 ) {
|
||||||
monitor->SetVideoWriterStartTime(queued_packet->timestamp);
|
monitor->SetVideoWriterStartTime(queued_packet->timestamp);
|
||||||
timersub(&queued_packet->timestamp, &recording, &video_offset);
|
timersub(&queued_packet->timestamp, &recording, &video_offset);
|
||||||
Info("Event video offset is %.3f sec (<0 means video starts early)",
|
Info("Event video offset is %.3f sec (<0 means video starts early)",
|
||||||
|
@ -912,7 +912,7 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
delete queued_packet;
|
delete queued_packet;
|
||||||
} // end while packets in the packetqueue
|
} // end while packets in the packetqueue
|
||||||
Debug(2, "Wrote %d queued packets", packet_count);
|
Debug(2, "Wrote %d queued packets", packet_count);
|
||||||
}
|
} // end if videostore is open or not
|
||||||
} // end if ! was recording
|
} // end if ! was recording
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -976,63 +976,65 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
}
|
}
|
||||||
} // end if keyframe or have_video_keyframe
|
} // end if keyframe or have_video_keyframe
|
||||||
|
|
||||||
ret = zm_send_packet_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
if ( monitor->DecodingEnabled() ) {
|
||||||
if ( ret < 0 ) {
|
ret = zm_send_packet_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
||||||
if ( AVERROR(EAGAIN) != ret ) {
|
|
||||||
Warning("Unable to receive frame %d: code %d %s. error count is %d",
|
|
||||||
frameCount, ret, av_make_error_string(ret).c_str(), error_count);
|
|
||||||
error_count += 1;
|
|
||||||
if ( error_count > 100 ) {
|
|
||||||
Error("Error count over 100, going to close and re-open stream");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
|
||||||
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
|
||||||
use_hwaccel = false;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
zm_av_packet_unref(&packet);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( error_count > 0 ) error_count--;
|
|
||||||
zm_dump_video_frame(mRawFrame, "raw frame from decoder");
|
|
||||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
|
||||||
if (
|
|
||||||
(hw_pix_fmt != AV_PIX_FMT_NONE)
|
|
||||||
&&
|
|
||||||
(mRawFrame->format == hw_pix_fmt)
|
|
||||||
) {
|
|
||||||
/* retrieve data from GPU to CPU */
|
|
||||||
ret = av_hwframe_transfer_data(hwFrame, mRawFrame, 0);
|
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
Error("Unable to transfer frame at frame %d: %s, continuing",
|
if ( AVERROR(EAGAIN) != ret ) {
|
||||||
frameCount, av_make_error_string(ret).c_str());
|
Warning("Unable to receive frame %d: code %d %s. error count is %d",
|
||||||
|
frameCount, ret, av_make_error_string(ret).c_str(), error_count);
|
||||||
|
error_count += 1;
|
||||||
|
if ( error_count > 100 ) {
|
||||||
|
Error("Error count over 100, going to close and re-open stream");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||||
|
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
||||||
|
use_hwaccel = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
zm_av_packet_unref(&packet);
|
zm_av_packet_unref(&packet);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
zm_dump_video_frame(hwFrame, "After hwtransfer");
|
if ( error_count > 0 ) error_count--;
|
||||||
|
zm_dump_video_frame(mRawFrame, "raw frame from decoder");
|
||||||
hwFrame->pts = mRawFrame->pts;
|
|
||||||
input_frame = hwFrame;
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
input_frame = mRawFrame;
|
|
||||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||||
}
|
if (
|
||||||
|
(hw_pix_fmt != AV_PIX_FMT_NONE)
|
||||||
|
&&
|
||||||
|
(mRawFrame->format == hw_pix_fmt)
|
||||||
|
) {
|
||||||
|
/* retrieve data from GPU to CPU */
|
||||||
|
ret = av_hwframe_transfer_data(hwFrame, mRawFrame, 0);
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
Error("Unable to transfer frame at frame %d: %s, continuing",
|
||||||
|
frameCount, av_make_error_string(ret).c_str());
|
||||||
|
zm_av_packet_unref(&packet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zm_dump_video_frame(hwFrame, "After hwtransfer");
|
||||||
|
|
||||||
|
hwFrame->pts = mRawFrame->pts;
|
||||||
|
input_frame = hwFrame;
|
||||||
|
} else {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if ( transfer_to_image(image, mFrame, input_frame) < 0 ) {
|
input_frame = mRawFrame;
|
||||||
Error("Failed to transfer from frame to image");
|
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||||
zm_av_packet_unref(&packet);
|
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||||
return -1;
|
}
|
||||||
}
|
#endif
|
||||||
|
#endif
|
||||||
|
if ( transfer_to_image(image, mFrame, input_frame) < 0 ) {
|
||||||
|
Error("Failed to transfer from frame to image");
|
||||||
|
zm_av_packet_unref(&packet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} // end if don't need to do decode
|
||||||
|
|
||||||
frameComplete = 1;
|
frameComplete = 1;
|
||||||
frameCount++;
|
frameCount++;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "zm.h"
|
||||||
|
#include "zm_font.h"
|
||||||
|
#include "zm_utils.h"
|
||||||
|
|
||||||
|
int ZmFont::ReadFontFile(const std::string &loc) {
|
||||||
|
FILE *f = fopen(loc.c_str(), "rb");
|
||||||
|
if ( !f ) return -1; // FILE NOT FOUND
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
stat(loc.c_str(), &st);
|
||||||
|
|
||||||
|
font = new ZMFONT;
|
||||||
|
|
||||||
|
size_t header_size = 8 + (sizeof(ZMFONT_BH) * NUM_FONT_SIZES);
|
||||||
|
|
||||||
|
// MAGIC + pad + BitmapHeaders
|
||||||
|
size_t readsize = fread(&font[0], 1, header_size, f);
|
||||||
|
if ( readsize < header_size ) {
|
||||||
|
delete font;
|
||||||
|
font = nullptr;
|
||||||
|
return -2; // EOF reached, invalid file
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( memcmp(font->MAGIC, "ZMFNT", 5) != 0 ) // Check whether magic is correct
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
for ( int i = 0; i < NUM_FONT_SIZES; i++ ) {
|
||||||
|
/* Character Width cannot be greater than 64 as a row is represented as a uint64_t,
|
||||||
|
height cannot be greater than 200(arbitary number which i have chosen, shouldn't need more than this) and
|
||||||
|
idx should not be more than filesize
|
||||||
|
*/
|
||||||
|
if ( (font->header[i].charWidth > 64 && font->header[i].charWidth == 0) ||
|
||||||
|
(font->header[i].charHeight > 200 && font->header[i].charHeight == 0) ||
|
||||||
|
(font->header[i].idx > st.st_size) ) {
|
||||||
|
delete font;
|
||||||
|
font = nullptr;
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
} // end foreach font size
|
||||||
|
|
||||||
|
datasize = st.st_size - header_size;
|
||||||
|
|
||||||
|
font->data = new uint64_t[datasize/sizeof(uint64_t)];
|
||||||
|
readsize = fread(&font->data[0], 1, datasize, f);
|
||||||
|
if ( readsize < datasize ) { // Shouldn't happen
|
||||||
|
delete[] font->data;
|
||||||
|
font->data = nullptr;
|
||||||
|
delete font;
|
||||||
|
font = nullptr;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZmFont::~ZmFont() {
|
||||||
|
if ( font && font->data ) {
|
||||||
|
delete[] font->data;
|
||||||
|
font->data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( font ) {
|
||||||
|
delete font;
|
||||||
|
font = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *ZmFont::GetBitmapData() {
|
||||||
|
return &font->data[font->header[size].idx];
|
||||||
|
}
|
3369
src/zm_font.h
3369
src/zm_font.h
File diff suppressed because it is too large
Load Diff
174
src/zm_image.cpp
174
src/zm_image.cpp
|
@ -18,7 +18,6 @@
|
||||||
//
|
//
|
||||||
#include "zm.h"
|
#include "zm.h"
|
||||||
#include "zm_font.h"
|
#include "zm_font.h"
|
||||||
#include "zm_bigfont.h"
|
|
||||||
#include "zm_image.h"
|
#include "zm_image.h"
|
||||||
#include "zm_utils.h"
|
#include "zm_utils.h"
|
||||||
#include "zm_rgb.h"
|
#include "zm_rgb.h"
|
||||||
|
@ -78,6 +77,9 @@ static deinterlace_4field_fptr_t fptr_deinterlace_4field_gray8;
|
||||||
/* Pointer to image buffer memory copy function */
|
/* Pointer to image buffer memory copy function */
|
||||||
imgbufcpy_fptr_t fptr_imgbufcpy;
|
imgbufcpy_fptr_t fptr_imgbufcpy;
|
||||||
|
|
||||||
|
/* Font */
|
||||||
|
static ZmFont font;
|
||||||
|
|
||||||
void Image::update_function_pointers() {
|
void Image::update_function_pointers() {
|
||||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||||
if ( pixels % 16 || pixels % 12 ) {
|
if ( pixels % 16 || pixels % 12 ) {
|
||||||
|
@ -489,6 +491,12 @@ void Image::Initialise() {
|
||||||
g_u_table = g_u_table_global;
|
g_u_table = g_u_table_global;
|
||||||
b_u_table = b_u_table_global;
|
b_u_table = b_u_table_global;
|
||||||
|
|
||||||
|
int res = font.ReadFontFile(config.font_file_location);
|
||||||
|
if ( res == -1 ) {
|
||||||
|
Panic("Invalid font location: %s", config.font_file_location);
|
||||||
|
} else if ( res == -2 || res == -3 || res == -4 ) {
|
||||||
|
Panic("Invalid font file.");
|
||||||
|
}
|
||||||
initialised = true;
|
initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,8 +1881,12 @@ const Coord Image::centreCoord( const char *text, int size=1 ) const {
|
||||||
line = text+index;
|
line = text+index;
|
||||||
line_no++;
|
line_no++;
|
||||||
}
|
}
|
||||||
int x = (width - (max_line_len * ZM_CHAR_WIDTH * size) ) / 2;
|
|
||||||
int y = (height - (line_no * LINE_HEIGHT * size) ) / 2;
|
font.SetFontSize(size-1);
|
||||||
|
uint16_t char_width = font.GetCharWidth();
|
||||||
|
uint16_t char_height = font.GetCharHeight();
|
||||||
|
int x = (width - (max_line_len * char_width )) / 2;
|
||||||
|
int y = (height - (line_no * char_height) ) / 2;
|
||||||
return Coord(x, y);
|
return Coord(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1920,8 +1932,16 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
/* 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 )
|
/* Bitmap decoding trick has been adopted from here:
|
||||||
{
|
https://lemire.me/blog/2018/02/21/iterating-over-set-bits-quickly/
|
||||||
|
*/
|
||||||
|
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 index = 0;
|
||||||
|
@ -1934,31 +1954,32 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour);
|
const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour);
|
||||||
const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour);
|
const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour);
|
||||||
const uint8_t fg_bw_col = fg_colour & 0xff;
|
const uint8_t fg_bw_col = fg_colour & 0xff;
|
||||||
const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder);
|
const Rgb fg_rgb_col = rgb_convert(fg_colour, subpixelorder);
|
||||||
const bool fg_trans = (fg_colour == RGB_TRANSPARENT);
|
|
||||||
|
|
||||||
const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour);
|
const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour);
|
||||||
const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour);
|
const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour);
|
||||||
const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour);
|
const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour);
|
||||||
const uint8_t bg_bw_col = bg_colour & 0xff;
|
const uint8_t bg_bw_col = bg_colour & 0xff;
|
||||||
const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder);
|
const Rgb bg_rgb_col = rgb_convert(bg_colour, subpixelorder);
|
||||||
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
||||||
|
|
||||||
int zm_text_bitmask = 0x80;
|
font.SetFontSize(size-1);
|
||||||
if ( size == 2 )
|
const uint16_t char_width = font.GetCharWidth();
|
||||||
zm_text_bitmask = 0x8000;
|
const uint16_t char_height = font.GetCharHeight();
|
||||||
|
const uint64_t *font_bitmap = font.GetBitmapData();
|
||||||
|
Debug(1, "Font size %d, char_width %d char_height %d", size, char_width, char_height);
|
||||||
|
|
||||||
while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) {
|
while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) {
|
||||||
|
unsigned int line_width = line_len * char_width;
|
||||||
unsigned int line_width = line_len * ZM_CHAR_WIDTH * size;
|
|
||||||
|
|
||||||
unsigned int lo_line_x = coord.X();
|
unsigned int lo_line_x = coord.X();
|
||||||
unsigned int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT * size);
|
unsigned int lo_line_y = coord.Y() + (line_no * char_height);
|
||||||
|
|
||||||
unsigned int min_line_x = 0;
|
unsigned int min_line_x = 0;
|
||||||
|
// FIXME What if line_width > width?
|
||||||
unsigned int max_line_x = width - line_width;
|
unsigned int max_line_x = width - line_width;
|
||||||
unsigned int min_line_y = 0;
|
unsigned int min_line_y = 0;
|
||||||
unsigned int max_line_y = height - (LINE_HEIGHT * size);
|
unsigned int max_line_y = height - char_height;
|
||||||
|
|
||||||
if ( lo_line_x > max_line_x )
|
if ( lo_line_x > max_line_x )
|
||||||
lo_line_x = max_line_x;
|
lo_line_x = max_line_x;
|
||||||
|
@ -1970,7 +1991,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
lo_line_y = min_line_y;
|
lo_line_y = min_line_y;
|
||||||
|
|
||||||
unsigned int hi_line_x = lo_line_x + line_width;
|
unsigned int hi_line_x = lo_line_x + line_width;
|
||||||
unsigned int hi_line_y = lo_line_y + (LINE_HEIGHT * size);
|
unsigned int hi_line_y = lo_line_y + char_height;
|
||||||
|
|
||||||
// Clip anything that runs off the right of the screen
|
// Clip anything that runs off the right of the screen
|
||||||
if ( hi_line_x > width )
|
if ( hi_line_x > width )
|
||||||
|
@ -1980,99 +2001,78 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
|
|
||||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||||
unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x];
|
unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += width ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += width ) {
|
||||||
unsigned char *temp_ptr = ptr;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
continue;
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
|
||||||
} 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++ ) {
|
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
if ( !bg_trans ) memset(temp_ptr, bg_bw_col, char_width);
|
||||||
if ( !fg_trans )
|
while ( f != 0 ) {
|
||||||
*temp_ptr = fg_bw_col;
|
uint64_t t = f & -f;
|
||||||
} else if ( !bg_trans ) {
|
int idx = char_width - __builtin_ctzll(f);
|
||||||
*temp_ptr = bg_bw_col;
|
*(temp_ptr + idx) = fg_bw_col;
|
||||||
}
|
f ^= t;
|
||||||
}
|
}
|
||||||
|
temp_ptr += char_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||||
unsigned int wc = width * colours;
|
unsigned int wc = width * colours;
|
||||||
|
|
||||||
unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours];
|
unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||||
unsigned char *temp_ptr = ptr;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
continue;
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
|
||||||
} 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 ) {
|
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
if ( !bg_trans ) {
|
||||||
if ( !fg_trans ) {
|
for ( int i = 0; i < char_width; i++ ) { // We need to set individual r,g,b components
|
||||||
RED_PTR_RGBA(temp_ptr) = fg_r_col;
|
unsigned char *colour_ptr = temp_ptr + (i*3);
|
||||||
GREEN_PTR_RGBA(temp_ptr) = fg_g_col;
|
RED_PTR_RGBA(colour_ptr) = bg_r_col;
|
||||||
BLUE_PTR_RGBA(temp_ptr) = fg_b_col;
|
GREEN_PTR_RGBA(colour_ptr) = bg_g_col;
|
||||||
}
|
BLUE_PTR_RGBA(colour_ptr) = bg_b_col;
|
||||||
} else if ( !bg_trans ) {
|
|
||||||
RED_PTR_RGBA(temp_ptr) = bg_r_col;
|
|
||||||
GREEN_PTR_RGBA(temp_ptr) = bg_g_col;
|
|
||||||
BLUE_PTR_RGBA(temp_ptr) = bg_b_col;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while ( f != 0 ) {
|
||||||
|
uint64_t t = f & -f;
|
||||||
|
int idx = char_width - __builtin_ctzll(f);
|
||||||
|
unsigned char *colour_ptr = temp_ptr + (idx*3);
|
||||||
|
RED_PTR_RGBA(colour_ptr) = fg_r_col;
|
||||||
|
GREEN_PTR_RGBA(colour_ptr) = fg_g_col;
|
||||||
|
BLUE_PTR_RGBA(colour_ptr) = fg_b_col;
|
||||||
|
f ^= t;
|
||||||
|
}
|
||||||
|
temp_ptr += char_width * colours;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
||||||
unsigned int wc = width * colours;
|
unsigned int wc = width * colours;
|
||||||
|
|
||||||
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2];
|
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x) << 2];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||||
Rgb* temp_ptr = (Rgb*)ptr;
|
Rgb* temp_ptr = (Rgb*)ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
continue;
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
|
||||||
} 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++ ) {
|
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
if ( !bg_trans ) {
|
||||||
if ( !fg_trans ) {
|
for ( int i = 0; i < char_width; i++ )
|
||||||
*temp_ptr = fg_rgb_col;
|
*(temp_ptr + i) = bg_rgb_col;
|
||||||
}
|
|
||||||
} else if ( !bg_trans ) {
|
|
||||||
*temp_ptr = bg_rgb_col;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
while ( f != 0 ) {
|
||||||
|
uint64_t t = f & -f;
|
||||||
|
int idx = char_width - __builtin_ctzll(f);
|
||||||
|
*(temp_ptr + idx) = fg_rgb_col;
|
||||||
|
f ^= t;
|
||||||
|
}
|
||||||
|
temp_ptr += char_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,8 @@
|
||||||
// This is the official SQL (and ordering of the fields) to load a Monitor.
|
// This is the official SQL (and ordering of the fields) to load a Monitor.
|
||||||
// It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended
|
// It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended
|
||||||
std::string load_monitor_sql =
|
std::string load_monitor_sql =
|
||||||
"SELECT `Id`, `Name`, `ServerId`, `StorageId`, `Type`, `Function`+0, `Enabled`, `LinkedMonitors`, "
|
"SELECT `Id`, `Name`, `ServerId`, `StorageId`, `Type`, `Function`+0, `Enabled`, `DecodingEnabled`, "
|
||||||
"`AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
"`LinkedMonitors`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
||||||
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, " // V4L Settings
|
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, " // V4L Settings
|
||||||
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, `Deinterlacing`, "
|
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, `Deinterlacing`, "
|
||||||
"`DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, "
|
"`DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, "
|
||||||
|
@ -282,6 +282,7 @@ Monitor::Monitor(
|
||||||
const unsigned int p_storage_id,
|
const unsigned int p_storage_id,
|
||||||
int p_function,
|
int p_function,
|
||||||
bool p_enabled,
|
bool p_enabled,
|
||||||
|
bool p_decoding_enabled,
|
||||||
const char *p_linked_monitors,
|
const char *p_linked_monitors,
|
||||||
Camera *p_camera,
|
Camera *p_camera,
|
||||||
int p_orientation,
|
int p_orientation,
|
||||||
|
@ -326,6 +327,7 @@ Monitor::Monitor(
|
||||||
storage_id( p_storage_id ),
|
storage_id( p_storage_id ),
|
||||||
function( (Function)p_function ),
|
function( (Function)p_function ),
|
||||||
enabled( p_enabled ),
|
enabled( p_enabled ),
|
||||||
|
decoding_enabled(p_decoding_enabled),
|
||||||
width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ),
|
width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ),
|
||||||
height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ),
|
height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ),
|
||||||
orientation( (Orientation)p_orientation ),
|
orientation( (Orientation)p_orientation ),
|
||||||
|
@ -366,12 +368,15 @@ Monitor::Monitor(
|
||||||
purpose( p_purpose ),
|
purpose( p_purpose ),
|
||||||
last_motion_score(0),
|
last_motion_score(0),
|
||||||
camera( p_camera ),
|
camera( p_camera ),
|
||||||
|
event(0),
|
||||||
n_zones( p_n_zones ),
|
n_zones( p_n_zones ),
|
||||||
zones( p_zones ),
|
zones( p_zones ),
|
||||||
timestamps( nullptr ),
|
timestamps( nullptr ),
|
||||||
images( nullptr ),
|
images( nullptr ),
|
||||||
privacy_bitmask( nullptr ),
|
privacy_bitmask( nullptr ),
|
||||||
event_delete_thread(nullptr)
|
event_delete_thread(nullptr),
|
||||||
|
n_linked_monitors(0),
|
||||||
|
linked_monitors(nullptr)
|
||||||
{
|
{
|
||||||
if ( analysis_fps > 0.0 ) {
|
if ( analysis_fps > 0.0 ) {
|
||||||
uint64_t usec = round(1000000*pre_event_count/analysis_fps);
|
uint64_t usec = round(1000000*pre_event_count/analysis_fps);
|
||||||
|
@ -458,6 +463,18 @@ Monitor::Monitor(
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do this here to save a few cycles with all the comparisons
|
||||||
|
decoding_enabled = !(
|
||||||
|
( function == RECORD or function == NODECT )
|
||||||
|
and
|
||||||
|
( savejpegs == 0 )
|
||||||
|
and
|
||||||
|
( videowriter == H264PASSTHROUGH )
|
||||||
|
and
|
||||||
|
!decoding_enabled
|
||||||
|
);
|
||||||
|
Debug(1, "Decoding enabled: %d", decoding_enabled);
|
||||||
|
|
||||||
memset(mem_ptr, 0, mem_size);
|
memset(mem_ptr, 0, mem_size);
|
||||||
shared_data->size = sizeof(SharedData);
|
shared_data->size = sizeof(SharedData);
|
||||||
shared_data->active = enabled;
|
shared_data->active = enabled;
|
||||||
|
@ -532,7 +549,6 @@ Monitor::Monitor(
|
||||||
|
|
||||||
start_time = last_fps_time = time( 0 );
|
start_time = last_fps_time = time( 0 );
|
||||||
|
|
||||||
event = 0;
|
|
||||||
|
|
||||||
Debug(1, "Monitor %s has function %d,\n"
|
Debug(1, "Monitor %s has function %d,\n"
|
||||||
"label format = '%s', label X = %d, label Y = %d, label size = %d,\n"
|
"label format = '%s', label X = %d, label Y = %d, label size = %d,\n"
|
||||||
|
@ -545,10 +561,6 @@ Monitor::Monitor(
|
||||||
|
|
||||||
//Set video recording flag for event start constructor and easy reference in code
|
//Set video recording flag for event start constructor and easy reference in code
|
||||||
videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo());
|
videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo());
|
||||||
|
|
||||||
n_linked_monitors = 0;
|
|
||||||
linked_monitors = nullptr;
|
|
||||||
|
|
||||||
} // Monitor::Monitor
|
} // Monitor::Monitor
|
||||||
|
|
||||||
bool Monitor::connect() {
|
bool Monitor::connect() {
|
||||||
|
@ -1432,7 +1444,8 @@ bool Monitor::Analyse() {
|
||||||
bool signal = shared_data->signal;
|
bool signal = shared_data->signal;
|
||||||
bool signal_change = (signal != last_signal);
|
bool signal_change = (signal != last_signal);
|
||||||
|
|
||||||
Debug(3, "Motion detection is enabled signal(%d) signal_change(%d)", signal, signal_change);
|
Debug(3, "Motion detection is enabled signal(%d) signal_change(%d) trigger state(%d)",
|
||||||
|
signal, signal_change, trigger_data->trigger_state);
|
||||||
|
|
||||||
if ( trigger_data->trigger_state != TRIGGER_OFF ) {
|
if ( trigger_data->trigger_state != TRIGGER_OFF ) {
|
||||||
unsigned int score = 0;
|
unsigned int score = 0;
|
||||||
|
@ -1511,7 +1524,11 @@ bool Monitor::Analyse() {
|
||||||
for ( int i = 0; i < n_linked_monitors; i++ ) {
|
for ( int i = 0; i < n_linked_monitors; i++ ) {
|
||||||
// TODO: Shouldn't we try to connect?
|
// TODO: Shouldn't we try to connect?
|
||||||
if ( linked_monitors[i]->isConnected() ) {
|
if ( linked_monitors[i]->isConnected() ) {
|
||||||
|
Debug(4, "Linked monitor %d %s is connected",
|
||||||
|
linked_monitors[i]->Id(), linked_monitors[i]->Name());
|
||||||
if ( linked_monitors[i]->hasAlarmed() ) {
|
if ( linked_monitors[i]->hasAlarmed() ) {
|
||||||
|
Debug(4, "Linked monitor %d %s is alarmed",
|
||||||
|
linked_monitors[i]->Id(), linked_monitors[i]->Name());
|
||||||
if ( !event ) {
|
if ( !event ) {
|
||||||
if ( first_link ) {
|
if ( first_link ) {
|
||||||
if ( cause.length() )
|
if ( cause.length() )
|
||||||
|
@ -1522,6 +1539,9 @@ bool Monitor::Analyse() {
|
||||||
}
|
}
|
||||||
noteSet.insert(linked_monitors[i]->Name());
|
noteSet.insert(linked_monitors[i]->Name());
|
||||||
score += 50;
|
score += 50;
|
||||||
|
} else {
|
||||||
|
Debug(4, "Linked monitor %d %s is not alarmed",
|
||||||
|
linked_monitors[i]->Id(), linked_monitors[i]->Name());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
|
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
|
||||||
|
@ -1842,7 +1862,7 @@ bool Monitor::Analyse() {
|
||||||
image_count++;
|
image_count++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // end Monitor::Analyze
|
} // end Monitor::Analyse
|
||||||
|
|
||||||
void Monitor::Reload() {
|
void Monitor::Reload() {
|
||||||
Debug(1, "Reloading monitor %s", name);
|
Debug(1, "Reloading monitor %s", name);
|
||||||
|
@ -1855,7 +1875,7 @@ void Monitor::Reload() {
|
||||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||||
// This seems to have fallen out of date.
|
// This seems to have fallen out of date.
|
||||||
snprintf(sql, sizeof(sql),
|
snprintf(sql, sizeof(sql),
|
||||||
"SELECT `Function`+0, `Enabled`, `LinkedMonitors`, `EventPrefix`, `LabelFormat`, "
|
"SELECT `Function`+0, `Enabled`, `DecodingEnabled`, `LinkedMonitors`, `EventPrefix`, `LabelFormat`, "
|
||||||
"`LabelX`, `LabelY`, `LabelSize`, `WarmupCount`, `PreEventCount`, `PostEventCount`, "
|
"`LabelX`, `LabelY`, `LabelSize`, `WarmupCount`, `PreEventCount`, `PostEventCount`, "
|
||||||
"`AlarmFrameCount`, `SectionLength`, `MinSectionLength`, `FrameSkip`, "
|
"`AlarmFrameCount`, `SectionLength`, `MinSectionLength`, `FrameSkip`, "
|
||||||
"`MotionFrameSkip`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`, "
|
"`MotionFrameSkip`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`, "
|
||||||
|
@ -1866,11 +1886,12 @@ void Monitor::Reload() {
|
||||||
if ( !row ) {
|
if ( !row ) {
|
||||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( MYSQL_ROW dbrow = row->mysql_row() ) {
|
if ( MYSQL_ROW dbrow = row->mysql_row() ) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
function = (Function)atoi(dbrow[index++]);
|
function = (Function)atoi(dbrow[index++]);
|
||||||
enabled = atoi(dbrow[index++]);
|
enabled = atoi(dbrow[index++]);
|
||||||
|
decoding_enabled = atoi(dbrow[index++]);
|
||||||
const char *p_linked_monitors = dbrow[index++];
|
const char *p_linked_monitors = dbrow[index++];
|
||||||
|
|
||||||
if ( dbrow[index] ) {
|
if ( dbrow[index] ) {
|
||||||
|
@ -2018,7 +2039,7 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
||||||
int n_monitors = mysql_num_rows(result);
|
int n_monitors = mysql_num_rows(result);
|
||||||
if ( n_monitors == 1 ) {
|
if ( n_monitors == 1 ) {
|
||||||
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
||||||
Debug(1, "Linking to monitor %d", link_ids[i]);
|
Debug(1, "Linking to monitor %d %s", atoi(dbrow[0]), dbrow[1]);
|
||||||
linked_monitors[count++] = new MonitorLink(link_ids[i], dbrow[1]);
|
linked_monitors[count++] = new MonitorLink(link_ids[i], dbrow[1]);
|
||||||
} else {
|
} else {
|
||||||
Warning("Can't link to monitor %d, invalid id, function or not enabled", link_ids[i]);
|
Warning("Can't link to monitor %d, invalid id, function or not enabled", link_ids[i]);
|
||||||
|
@ -2129,6 +2150,7 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
|
||||||
std::string type = dbrow[col] ? dbrow[col] : ""; col++;
|
std::string type = dbrow[col] ? dbrow[col] : ""; col++;
|
||||||
Function function = (Function)atoi(dbrow[col]); col++;
|
Function function = (Function)atoi(dbrow[col]); col++;
|
||||||
int enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
int enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||||
|
int decoding_enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||||
const char *linked_monitors = dbrow[col];col++;
|
const char *linked_monitors = dbrow[col];col++;
|
||||||
|
|
||||||
double analysis_fps = dbrow[col] ? strtod(dbrow[col], nullptr) : 0; col++;
|
double analysis_fps = dbrow[col] ? strtod(dbrow[col], nullptr) : 0; col++;
|
||||||
|
@ -2405,6 +2427,7 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
|
||||||
storage_id,
|
storage_id,
|
||||||
(int)function,
|
(int)function,
|
||||||
enabled,
|
enabled,
|
||||||
|
decoding_enabled,
|
||||||
linked_monitors,
|
linked_monitors,
|
||||||
camera,
|
camera,
|
||||||
orientation,
|
orientation,
|
||||||
|
|
|
@ -253,6 +253,7 @@ protected:
|
||||||
CameraType type;
|
CameraType type;
|
||||||
Function function; // What the monitor is doing
|
Function function; // What the monitor is doing
|
||||||
bool enabled; // Whether the monitor is enabled or asleep
|
bool enabled; // Whether the monitor is enabled or asleep
|
||||||
|
bool decoding_enabled; // Whether the monitor will decode h264/h265 packets
|
||||||
unsigned int width; // Normally the same as the camera, but not if partly rotated
|
unsigned int width; // Normally the same as the camera, but not if partly rotated
|
||||||
unsigned int height; // Normally the same as the camera, but not if partly rotated
|
unsigned int height; // Normally the same as the camera, but not if partly rotated
|
||||||
bool v4l_multi_buffer;
|
bool v4l_multi_buffer;
|
||||||
|
@ -378,6 +379,7 @@ public:
|
||||||
unsigned int p_storage_id,
|
unsigned int p_storage_id,
|
||||||
int p_function,
|
int p_function,
|
||||||
bool p_enabled,
|
bool p_enabled,
|
||||||
|
bool p_decoding_enabled,
|
||||||
const char *p_linked_monitors,
|
const char *p_linked_monitors,
|
||||||
Camera *p_camera,
|
Camera *p_camera,
|
||||||
int p_orientation,
|
int p_orientation,
|
||||||
|
@ -445,6 +447,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
inline bool DecodingEnabled() const {
|
||||||
|
return decoding_enabled;
|
||||||
|
}
|
||||||
inline const char *EventPrefix() const { return event_prefix; }
|
inline const char *EventPrefix() const { return event_prefix; }
|
||||||
inline bool Ready() const {
|
inline bool Ready() const {
|
||||||
if ( function <= MONITOR )
|
if ( function <= MONITOR )
|
||||||
|
|
|
@ -6,7 +6,7 @@ $data = array();
|
||||||
// INITIALIZE AND CHECK SANITY
|
// INITIALIZE AND CHECK SANITY
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( !canEdit('Events') ) $message = 'Insufficient permissions for user '.$user['Username'];
|
if ( !canView('Events') ) $message = 'Insufficient permissions for user '.$user['Username'];
|
||||||
|
|
||||||
if ( empty($_REQUEST['task']) ) {
|
if ( empty($_REQUEST['task']) ) {
|
||||||
$message = 'Must specify a task';
|
$message = 'Must specify a task';
|
||||||
|
@ -74,10 +74,22 @@ if ( isset($_REQUEST['limit']) ) {
|
||||||
|
|
||||||
switch ( $task ) {
|
switch ( $task ) {
|
||||||
case 'archive' :
|
case 'archive' :
|
||||||
|
foreach ( $eids as $eid ) archiveRequest($task, $eid);
|
||||||
|
break;
|
||||||
case 'unarchive' :
|
case 'unarchive' :
|
||||||
|
# The idea is that anyone can archive, but only people with Event Edit permission can unarchive..
|
||||||
|
if ( !canEdit('Events') ) {
|
||||||
|
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
foreach ( $eids as $eid ) archiveRequest($task, $eid);
|
foreach ( $eids as $eid ) archiveRequest($task, $eid);
|
||||||
break;
|
break;
|
||||||
case 'delete' :
|
case 'delete' :
|
||||||
|
if ( !canEdit('Events') ) {
|
||||||
|
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
|
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
|
||||||
break;
|
break;
|
||||||
case 'query' :
|
case 'query' :
|
||||||
|
@ -217,12 +229,12 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
||||||
$event = new ZM\Event($row);
|
$event = new ZM\Event($row);
|
||||||
|
|
||||||
$scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width());
|
$scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width());
|
||||||
$imgSrc = $event->getThumbnailSrc(array(),'&');
|
$imgSrc = $event->getThumbnailSrc(array(), '&');
|
||||||
$streamSrc = $event->getStreamSrc(array(
|
$streamSrc = $event->getStreamSrc(array(
|
||||||
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&');
|
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&');
|
||||||
|
|
||||||
// Modify the row data as needed
|
// Modify the row data as needed
|
||||||
$row['imgHtml'] = '<img id="thumbnail' .$event->Id(). '" src="' .$imgSrc. '" alt="' .validHtmlStr('Event ' .$event->Id()). '" style="width:' .validInt($event->ThumbnailWidth()). 'px;height:' .validInt($event->ThumbnailHeight()).'px;" stream_src="' .$streamSrc. '" still_src="' .$imgSrc. '"/>';
|
$row['imgHtml'] = '<img id="thumbnail' .$event->Id(). '" src="' .$imgSrc. '" alt="Event '.$event->Id().'" width="' .validInt($event->ThumbnailWidth()). '" height="' .validInt($event->ThumbnailHeight()).'" stream_src="' .$streamSrc. '" still_src="' .$imgSrc. '"/>';
|
||||||
$row['Name'] = validHtmlStr($row['Name']);
|
$row['Name'] = validHtmlStr($row['Name']);
|
||||||
$row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No');
|
$row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No');
|
||||||
$row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No');
|
$row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No');
|
||||||
|
|
|
@ -161,15 +161,30 @@ function queryRequest($eid, $search, $advsearch, $sort, $offset, $order, $limit)
|
||||||
$returned_rows = array();
|
$returned_rows = array();
|
||||||
foreach ( array_slice($filtered_rows, $offset, $limit) as $row ) {
|
foreach ( array_slice($filtered_rows, $offset, $limit) as $row ) {
|
||||||
if ( ZM_WEB_LIST_THUMBS ) {
|
if ( ZM_WEB_LIST_THUMBS ) {
|
||||||
|
|
||||||
|
# Build the path to the potential analysis image
|
||||||
|
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $row['FrameId']);
|
||||||
|
$analPath = $Event->Path().'/'.$analImage;
|
||||||
|
$alarmFrame = $row['Type'] == 'Alarm';
|
||||||
|
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
||||||
|
|
||||||
|
# Our base img source component, which we will add on to
|
||||||
$base_img_src = '?view=image&fid=' .$row['Id'];
|
$base_img_src = '?view=image&fid=' .$row['Id'];
|
||||||
|
|
||||||
|
# if an analysis images exists, use it as the thumbnail
|
||||||
|
if ( $hasAnalImage ) $base_img_src .= '&show=analyse';
|
||||||
|
|
||||||
|
# Build the subcomponents needed for the image source
|
||||||
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
||||||
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
|
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
|
||||||
$thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"';
|
$thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"';
|
||||||
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$row['EventId']. '_' .$row['FrameId']. '.jpg';
|
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$row['EventId']. '_' .$row['FrameId']. '.jpg';
|
||||||
|
|
||||||
|
# Assemble the scaled and unscaled image source image source components
|
||||||
$img_src = join('&', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
|
$img_src = join('&', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
|
||||||
$full_img_src = join('&', array_filter(array($base_img_src, $thmb_fn)));
|
$full_img_src = join('&', array_filter(array($base_img_src, $thmb_fn)));
|
||||||
$frame_src = '?view=frame&eid=' .$row['EventId']. '&fid=' .$row['FrameId'];
|
|
||||||
|
|
||||||
|
# finally, we assemble the the entire thumbnail img src structure, whew
|
||||||
$row['Thumbnail'] = '<img src="' .$img_src. '" '.$thmb_width. ' ' .$thmb_height. 'img_src="' .$img_src. '" full_img_src="' .$full_img_src. '">';
|
$row['Thumbnail'] = '<img src="' .$img_src. '" '.$thmb_width. ' ' .$thmb_height. 'img_src="' .$img_src. '" full_img_src="' .$full_img_src. '">';
|
||||||
}
|
}
|
||||||
$returned_rows[] = $row;
|
$returned_rows[] = $row;
|
||||||
|
|
|
@ -37,11 +37,39 @@ if ( !canEdit('Monitors') ) return;
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>
|
<div class="form-group" id="FunctionFunction">
|
||||||
|
<label for="newFunction"><?php echo translate('Function') ?></label>
|
||||||
<?php echo htmlSelect('newFunction', ZM\getMonitorFunctionTypes(), null, array('id'=>'newFunction')); ?>
|
<?php echo htmlSelect('newFunction', ZM\getMonitorFunctionTypes(), null, array('id'=>'newFunction')); ?>
|
||||||
<label for="newEnabled"><?php echo translate('Enabled') ?></label>
|
<div id="function_help">
|
||||||
|
<?php
|
||||||
|
foreach ( ZM\getMonitorFunctionTypes() as $fn => $translated ) {
|
||||||
|
if ( isset($OLANG['FUNCTION_'.strtoupper($fn)]) ) {
|
||||||
|
echo '<div class="form-text" id="'.$fn.'Help">'.$OLANG['FUNCTION_'.strtoupper($fn)]['Help'].'</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="FunctionAnalysisEnabled">
|
||||||
|
<label for="newEnabled"><?php echo translate('Analysis Enabled') ?></label>
|
||||||
<input type="checkbox" name="newEnabled" id="newEnabled" value="1"/>
|
<input type="checkbox" name="newEnabled" id="newEnabled" value="1"/>
|
||||||
</p>
|
<?php
|
||||||
|
if ( isset($OLANG['FUNCTION_ANALYSIS_ENABLED']) ) {
|
||||||
|
echo '<div class="form-text">'.$OLANG['FUNCTION_ANALYSIS_ENABLED']['Help'].'</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="FunctionDecodingEnabled">
|
||||||
|
<label for="newDecodingEnabled"><?php echo translate('Decoding Enabled') ?></label>
|
||||||
|
<input type="checkbox" name="newDecodingEnabled" id="newDecodingEnabled" value="1"/>
|
||||||
|
<?php
|
||||||
|
if ( isset($OLANG['FUNCTION_DECODING_ENABLED']) ) {
|
||||||
|
echo '<div class="form-text">'.$OLANG['FUNCTION_DECODING_ENABLED']['Help'].'</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="funcSaveBtn btn btn-primary"><?php echo translate('Save') ?></button>
|
<button type="button" class="funcSaveBtn btn btn-primary"><?php echo translate('Save') ?></button>
|
||||||
|
|
|
@ -6,6 +6,7 @@ if ( empty($_REQUEST['fid']) ) ajaxError('Frame Id Not Provided');
|
||||||
$eid = $_REQUEST['eid'];
|
$eid = $_REQUEST['eid'];
|
||||||
$fid = $_REQUEST['fid'];
|
$fid = $_REQUEST['fid'];
|
||||||
$row = ( isset($_REQUEST['row']) ) ? $_REQUEST['row'] : '';
|
$row = ( isset($_REQUEST['row']) ) ? $_REQUEST['row'] : '';
|
||||||
|
$raw = isset($_REQUEST['raw']);
|
||||||
$data = array();
|
$data = array();
|
||||||
|
|
||||||
// Not sure if this is required
|
// Not sure if this is required
|
||||||
|
@ -16,8 +17,28 @@ if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['html'] = getStatsTableHTML($eid, $fid, $row);
|
if ( $raw ) {
|
||||||
$data['id'] = '#contentStatsTable' .$row;
|
$sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId';
|
||||||
|
$stat = dbFetchOne( $sql, NULL, array( $eid, $fid ) );
|
||||||
|
if ( $stat ) {
|
||||||
|
$stat['ZoneName'] = validHtmlStr($stat['ZoneName']);
|
||||||
|
$stat['PixelDiff'] = validHtmlStr($stat['PixelDiff']);
|
||||||
|
$stat['AlarmPixels'] = sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) );
|
||||||
|
$stat['FilterPixels'] = sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) );
|
||||||
|
$stat['BlobPixels'] = sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) );
|
||||||
|
$stat['Blobs'] = validHtmlStr($stat['Blobs']);
|
||||||
|
if ( $stat['Blobs'] > 1 ) {
|
||||||
|
$stat['BlobSizes'] = sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) );
|
||||||
|
} else {
|
||||||
|
$stat['BlobSizes'] = sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] );
|
||||||
|
}
|
||||||
|
$stat['AlarmLimits'] = validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']);
|
||||||
|
}
|
||||||
|
$data['raw'] = $stat;
|
||||||
|
} else {
|
||||||
|
$data['html'] = getStatsTableHTML($eid, $fid, $row);
|
||||||
|
$data['id'] = '#contentStatsTable' .$row;
|
||||||
|
}
|
||||||
|
|
||||||
ajaxResponse($data);
|
ajaxResponse($data);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -330,7 +330,7 @@ function collectData() {
|
||||||
foreach ( $postFuncs as $element=>$func )
|
foreach ( $postFuncs as $element=>$func )
|
||||||
$sqlData[$element] = eval('return( '.$func.'( $sqlData ) );');
|
$sqlData[$element] = eval('return( '.$func.'( $sqlData ) );');
|
||||||
$data[] = $sqlData;
|
$data[] = $sqlData;
|
||||||
if ( isset($limi) && ++$count >= $limit )
|
if ( isset($limit) && ++$count >= $limit )
|
||||||
break;
|
break;
|
||||||
} # end foreach
|
} # end foreach
|
||||||
} # end if have limit == 1
|
} # end if have limit == 1
|
||||||
|
@ -364,6 +364,7 @@ switch ( $_REQUEST['layout'] ) {
|
||||||
$response = array( strtolower(validJsStr($_REQUEST['entity'])) => $data );
|
$response = array( strtolower(validJsStr($_REQUEST['entity'])) => $data );
|
||||||
if ( isset($_REQUEST['loopback']) )
|
if ( isset($_REQUEST['loopback']) )
|
||||||
$response['loopback'] = validJsStr($_REQUEST['loopback']);
|
$response['loopback'] = validJsStr($_REQUEST['loopback']);
|
||||||
|
#ZM\Warning(print_r($response, true));
|
||||||
ajaxResponse($response);
|
ajaxResponse($response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,23 +116,23 @@ class GroupsController extends AppController {
|
||||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$this->Group->id = $id;
|
||||||
if ( $this->Group->save($this->request->data) ) {
|
if ( $this->Group->save($this->request->data) ) {
|
||||||
return $this->flash(
|
$message = 'Saved';
|
||||||
__('The group has been saved.'),
|
|
||||||
array('action' => 'index')
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
$message = 'Error';
|
$message = 'Error';
|
||||||
|
// if there is a validation message, use it
|
||||||
|
if ( !$this->group->validates() ) {
|
||||||
|
$message .= ': '.$this->Group->validationErrors;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} # end if post/put
|
||||||
$options = array('conditions' => array('Group.' . $this->Group->primaryKey => $id));
|
|
||||||
$this->request->data = $this->Group->find('first', $options);
|
$group = $this->Group->findById($id);
|
||||||
}
|
|
||||||
$monitors = $this->Group->Monitor->find('list');
|
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'monitors'=> $monitors,
|
'group' => $group,
|
||||||
'_serialize' => array('message')
|
'_serialize' => array('group')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ class Monitor extends ZM_Object {
|
||||||
'Type' => 'Ffmpeg',
|
'Type' => 'Ffmpeg',
|
||||||
'Function' => 'Mocord',
|
'Function' => 'Mocord',
|
||||||
'Enabled' => array('type'=>'boolean','default'=>1),
|
'Enabled' => array('type'=>'boolean','default'=>1),
|
||||||
|
'DecodingEnabled' => array('type'=>'boolean','default'=>1),
|
||||||
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
|
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
|
||||||
'Triggers' => array('type'=>'set','default'=>''),
|
'Triggers' => array('type'=>'set','default'=>''),
|
||||||
'ONVIF_URL' => '',
|
'ONVIF_URL' => '',
|
||||||
|
|
|
@ -11,16 +11,8 @@ class ZM_Object {
|
||||||
|
|
||||||
$row = NULL;
|
$row = NULL;
|
||||||
if ( $IdOrRow ) {
|
if ( $IdOrRow ) {
|
||||||
global $object_cache;
|
|
||||||
if ( ! isset($object_cache[$class]) ) {
|
|
||||||
$object_cache[$class] = array();
|
|
||||||
}
|
|
||||||
$cache = &$object_cache[$class];
|
|
||||||
|
|
||||||
if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) {
|
if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) {
|
||||||
if ( isset($cache[$IdOrRow]) ) {
|
|
||||||
return $cache[$IdOrRow];
|
|
||||||
}
|
|
||||||
$table = $class::$table;
|
$table = $class::$table;
|
||||||
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow));
|
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow));
|
||||||
if ( !$row ) {
|
if ( !$row ) {
|
||||||
|
@ -34,6 +26,11 @@ class ZM_Object {
|
||||||
foreach ($row as $k => $v) {
|
foreach ($row as $k => $v) {
|
||||||
$this->{$k} = $v;
|
$this->{$k} = $v;
|
||||||
}
|
}
|
||||||
|
global $object_cache;
|
||||||
|
if ( ! isset($object_cache[$class]) ) {
|
||||||
|
$object_cache[$class] = array();
|
||||||
|
}
|
||||||
|
$cache = &$object_cache[$class];
|
||||||
$cache[$row['Id']] = $this;
|
$cache[$row['Id']] = $this;
|
||||||
}
|
}
|
||||||
} # end if isset($IdOrRow)
|
} # end if isset($IdOrRow)
|
||||||
|
@ -253,8 +250,8 @@ class ZM_Object {
|
||||||
} else if ( property_exists($this, $field) ) {
|
} else if ( property_exists($this, $field) ) {
|
||||||
$type = (array_key_exists($field, $this->defaults) && is_array($this->defaults[$field])) ? $this->defaults[$field]['type'] : 'scalar';
|
$type = (array_key_exists($field, $this->defaults) && is_array($this->defaults[$field])) ? $this->defaults[$field]['type'] : 'scalar';
|
||||||
if ( $type == 'set' ) {
|
if ( $type == 'set' ) {
|
||||||
$old_value = is_array($this->$field) ? $this->$field : explode(',', $this->$field);
|
$old_value = is_array($this->$field) ? $this->$field : ($this->$field ? explode(',', $this->$field) : array());
|
||||||
$new_value = is_array($value) ? $value : explode(',', $value);
|
$new_value = is_array($value) ? $value : ($value ? explode(',', $value) : array());
|
||||||
|
|
||||||
$diff = array_recursive_diff($old_value, $new_value);
|
$diff = array_recursive_diff($old_value, $new_value);
|
||||||
if ( count($diff) ) {
|
if ( count($diff) ) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ if ( $action == 'save' ) {
|
||||||
'Controllable' => 0,
|
'Controllable' => 0,
|
||||||
'TrackMotion' => 0,
|
'TrackMotion' => 0,
|
||||||
'Enabled' => 0,
|
'Enabled' => 0,
|
||||||
|
'DecodingEnabled' => 0,
|
||||||
'Exif' => 0,
|
'Exif' => 0,
|
||||||
'RTSPDescribe' => 0,
|
'RTSPDescribe' => 0,
|
||||||
'V4LMultiBuffer' => '',
|
'V4LMultiBuffer' => '',
|
||||||
|
@ -82,7 +83,7 @@ if ( $action == 'save' ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$changes = $monitor->changes($_REQUEST['newMonitor'], $types);
|
$changes = $monitor->changes($_REQUEST['newMonitor']);
|
||||||
$restart = false;
|
$restart = false;
|
||||||
|
|
||||||
if ( count($changes) ) {
|
if ( count($changes) ) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ function validateUser($username='', $password='') {
|
||||||
|
|
||||||
function userLogout() {
|
function userLogout() {
|
||||||
global $user;
|
global $user;
|
||||||
ZM\Info('User "'.$user['Username'].'" logged out');
|
ZM\Info('User "'.($user?$user['Username']:'no one').'" logged out');
|
||||||
$user = null;// unset only clears the local variable
|
$user = null;// unset only clears the local variable
|
||||||
zm_session_clear();
|
zm_session_clear();
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,26 @@ function getAuthUser($auth) {
|
||||||
} // end if $auth == $authHash
|
} // end if $auth == $authHash
|
||||||
} // end foreach hour
|
} // end foreach hour
|
||||||
} // end foreach user
|
} // end foreach user
|
||||||
|
|
||||||
|
if ( isset($_SESSION['username']) ) {
|
||||||
|
# In a multi-server case, we might be logged in as another user and so the auth hash didn't work
|
||||||
|
$sql = 'SELECT * FROM Users WHERE Enabled = 1 AND Username != ?';
|
||||||
|
|
||||||
|
foreach ( dbFetchAll($sql, NULL, $values) as $user ) {
|
||||||
|
$now = time();
|
||||||
|
for ( $i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600 ) { // Try for last TTL hours
|
||||||
|
$time = localtime($now);
|
||||||
|
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5];
|
||||||
|
$authHash = md5($authKey);
|
||||||
|
|
||||||
|
if ( $auth == $authHash ) {
|
||||||
|
return $user;
|
||||||
|
} // end if $auth == $authHash
|
||||||
|
} // end foreach hour
|
||||||
|
} // end foreach user
|
||||||
|
} // end if
|
||||||
} // end if using auth hash
|
} // end if using auth hash
|
||||||
|
|
||||||
ZM\Error("Unable to authenticate user from auth hash '$auth'");
|
ZM\Error("Unable to authenticate user from auth hash '$auth'");
|
||||||
return null;
|
return null;
|
||||||
} // end getAuthUser($auth)
|
} // end getAuthUser($auth)
|
||||||
|
|
|
@ -128,7 +128,7 @@ function dbEscape( $string ) {
|
||||||
return $dbConn->quote($string);
|
return $dbConn->quote($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbQuery($sql, $params=NULL) {
|
function dbQuery($sql, $params=NULL, $debug = false) {
|
||||||
global $dbConn;
|
global $dbConn;
|
||||||
if ( dbLog($sql, true) )
|
if ( dbLog($sql, true) )
|
||||||
return;
|
return;
|
||||||
|
@ -145,7 +145,7 @@ function dbQuery($sql, $params=NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( defined('ZM_DB_DEBUG') ) {
|
if ( defined('ZM_DB_DEBUG') or $debug ) {
|
||||||
ZM\Debug("SQL: $sql values:" . ($params?implode(',',$params):''));
|
ZM\Debug("SQL: $sql values:" . ($params?implode(',',$params):''));
|
||||||
}
|
}
|
||||||
$result = $dbConn->query($sql);
|
$result = $dbConn->query($sql);
|
||||||
|
@ -154,7 +154,7 @@ function dbQuery($sql, $params=NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( defined('ZM_DB_DEBUG') ) {
|
if ( defined('ZM_DB_DEBUG') or $debug ) {
|
||||||
ZM\Debug('SQL: '.$sql.' '.($params?implode(',',$params):'').' rows: '.$result->rowCount());
|
ZM\Debug('SQL: '.$sql.' '.($params?implode(',',$params):'').' rows: '.$result->rowCount());
|
||||||
}
|
}
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
|
@ -189,13 +189,13 @@ function dbFetchOne($sql, $col=false, $params=NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbFetchAll($sql, $col=false, $params=NULL) {
|
function dbFetchAll($sql, $col=false, $params=NULL) {
|
||||||
|
$dbRows = array();
|
||||||
$result = dbQuery($sql, $params);
|
$result = dbQuery($sql, $params);
|
||||||
if ( ! $result ) {
|
if ( ! $result ) {
|
||||||
ZM\Error("SQL-ERR dbFetchAll no result, statement was '".$sql."'".($params ? 'params: '.join(',', $params) : ''));
|
ZM\Error("SQL-ERR dbFetchAll no result, statement was '".$sql."'".($params ? 'params: '.join(',', $params) : ''));
|
||||||
return false;
|
return $dbRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbRows = array();
|
|
||||||
while ( $dbRow = $result->fetch(PDO::FETCH_ASSOC) )
|
while ( $dbRow = $result->fetch(PDO::FETCH_ASSOC) )
|
||||||
$dbRows[] = $col ? $dbRow[$col] : $dbRow;
|
$dbRows[] = $col ? $dbRow[$col] : $dbRow;
|
||||||
return $dbRows;
|
return $dbRows;
|
||||||
|
|
|
@ -1200,8 +1200,8 @@ function sortHeader($field, $querySep='&') {
|
||||||
'?view='.$view,
|
'?view='.$view,
|
||||||
'page=1'.(isset($_REQUEST['filter'])?$_REQUEST['filter']['query']:''),
|
'page=1'.(isset($_REQUEST['filter'])?$_REQUEST['filter']['query']:''),
|
||||||
'sort_field='.$field,
|
'sort_field='.$field,
|
||||||
'sort_asc='.($_REQUEST['sort_field'] == $field ? !$_REQUEST['sort_asc'] : 0),
|
'sort_asc='.( ( isset($_REQUEST['sort_field']) and ( $_REQUEST['sort_field'] == $field ) ) ? !$_REQUEST['sort_asc'] : 0),
|
||||||
'limit='.validInt($_REQUEST['limit']),
|
'limit='.(isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : ''),
|
||||||
(isset($_REQUEST['eid']) ? 'eid='.$_REQUEST['eid'] : '' ),
|
(isset($_REQUEST['eid']) ? 'eid='.$_REQUEST['eid'] : '' ),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -2149,14 +2149,15 @@ function folder_size($dir) {
|
||||||
} // end function folder_size
|
} // end function folder_size
|
||||||
|
|
||||||
function human_filesize($size, $precision = 2) {
|
function human_filesize($size, $precision = 2) {
|
||||||
$units = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
|
$units = array('B ','kB','MB','GB','TB','PB','EB','ZB','YB');
|
||||||
$step = 1024;
|
$step = 1024;
|
||||||
$i = 0;
|
$i = 0;
|
||||||
while (($size / $step) > 0.9) {
|
while (($size / $step) > 0.9) {
|
||||||
$size = $size / $step;
|
$size = $size / $step;
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
return round($size, $precision).$units[$i];
|
# The idea is that we can right align this and have the digits columns line up nicely.
|
||||||
|
return sprintf('%.'.$precision.'f', round($size, $precision)).$units[$i];
|
||||||
}
|
}
|
||||||
|
|
||||||
function csrf_startup() {
|
function csrf_startup() {
|
||||||
|
|
|
@ -1073,6 +1073,70 @@ $OLANG = array(
|
||||||
certainly not what you want! To unlink monitors you can ctrl-click.
|
certainly not what you want! To unlink monitors you can ctrl-click.
|
||||||
'
|
'
|
||||||
),
|
),
|
||||||
|
'FUNCTION_NONE' => array(
|
||||||
|
'Help' => '
|
||||||
|
In None mode no processes are started. No capturing will occur.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_MONITOR' => array(
|
||||||
|
'Help' => '
|
||||||
|
In Monitor mode the capture process (zmc) will connect to the camera and stream data.
|
||||||
|
It will be decoded if necessary and live viewing will be possible.
|
||||||
|
No motion detection will be performed. This monitor type cannot save video.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_MODECT' => array(
|
||||||
|
'Help' => '
|
||||||
|
In Modect mode the capture process (zmc) will connect to the camera and stream data.
|
||||||
|
It will be decoded if necessary and live viewing will be possible.
|
||||||
|
In addition a process (zma) will analyse the video for motion.
|
||||||
|
When motion is detected, events will be created and video will be stored.
|
||||||
|
Motion data will be stored in the database for each event.
|
||||||
|
Events may also be triggered externally (zmtrigger) or by linked monitors.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_RECORD' => array(
|
||||||
|
'Help' => '
|
||||||
|
In Record mode the capture process (zmc) will connect to the camera and stream data.
|
||||||
|
It will be decoded if necessary and live viewing will be possible.
|
||||||
|
In addition a process (zma) will run but will not perform motion detection.
|
||||||
|
Events will be created at fixed intervals and video will be stored.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_MOCORD' => array(
|
||||||
|
'Help' => '
|
||||||
|
In Mocord mode the capture process (zmc) will connect to the camera and stream data.
|
||||||
|
It will be decoded if necessary and live viewing will be possible.
|
||||||
|
In addition a process (zma) will analyse the video for motion.
|
||||||
|
Events will be created at fixed intervals or at start and stop of motion.
|
||||||
|
Video will always be stored to disk and events will have the motion data stored in the database.
|
||||||
|
Events may also be triggered externally (zmtrigger) or by linked monitors.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_NODECT' => array(
|
||||||
|
'Help' => '
|
||||||
|
In Nodect mode the capture process (zmc) will connect to the camera and stream data.
|
||||||
|
It will be decoded if necessary and live viewing will be possible.
|
||||||
|
In addition a process (zma) will run and will check any linked cameras for their alarm status.
|
||||||
|
When linked cameras or an external trigger (zmtrigger) are alarmed, events will be created
|
||||||
|
and video will be stored. No other motion detection will occur.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_ANALYSIS_ENABLED' => array(
|
||||||
|
'Help' => '
|
||||||
|
When in Modect, Mocord, Nodect or RECORD mode the analysis process can be turned on/off.
|
||||||
|
This setting sets the default state when the process starts up.
|
||||||
|
It can then be turned on/off through external triggers zmtrigger zmu or the web ui.
|
||||||
|
When not enabled no motion detection or linked monitor checking will be performed and
|
||||||
|
no events will be created. The zma process will still be running waiting to be enabled.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
'FUNCTION_DECODING_ENABLED' => array(
|
||||||
|
'Help' => '
|
||||||
|
When in Record or Nodect mode and using H264Passthrough with no jpegs being saved, we can
|
||||||
|
optionally choose to not decode the H264/H265 packets. This will drastically reduce cpu use
|
||||||
|
but will make live view unavailable for this monitor.'
|
||||||
|
),
|
||||||
|
|
||||||
// 'LANG_DEFAULT' => array(
|
// 'LANG_DEFAULT' => array(
|
||||||
// 'Prompt' => "This is a new prompt for this option",
|
// 'Prompt' => "This is a new prompt for this option",
|
||||||
|
|
|
@ -728,23 +728,11 @@ li.search-choice {
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom {
|
.zoom {
|
||||||
padding: 50px;
|
|
||||||
transition: transform .2s; /* Animation */
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom:hover {
|
|
||||||
transform-origin: 70% 50%;
|
transform-origin: 70% 50%;
|
||||||
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
|
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom-right {
|
.zoom-console {
|
||||||
padding: 0px;
|
|
||||||
transition: transform .2s; /* Animation */
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-right:hover {
|
|
||||||
transform-origin: 0% 50%;
|
transform-origin: 0% 50%;
|
||||||
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
|
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
|
||||||
}
|
}
|
||||||
|
@ -753,3 +741,6 @@ a.flip {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: -20px;
|
margin-right: -20px;
|
||||||
}
|
}
|
||||||
|
#content table.major .colDiskSpace {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
|
@ -99,3 +99,6 @@
|
||||||
.StatusFilter select {
|
.StatusFilter select {
|
||||||
min-width: 130px;
|
min-width: 130px;
|
||||||
}
|
}
|
||||||
|
#FunctionFunction {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
|
@ -42,3 +42,6 @@ input[name="newMonitor[Height]"] {
|
||||||
select.chosen {
|
select.chosen {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
tr td:first-child {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ function exportEventDetail($event, $exportFrames, $exportImages) {
|
||||||
<tr><th scope="row"><?php echo translate('Monitor') ?></th><td><?php echo validHtmlStr($event->Monitor()->Name()) ?> (<?php echo $event->MonitorId() ?>)</td></tr>
|
<tr><th scope="row"><?php echo translate('Monitor') ?></th><td><?php echo validHtmlStr($event->Monitor()->Name()) ?> (<?php echo $event->MonitorId() ?>)</td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('Cause') ?></th><td><?php echo validHtmlStr($event->Cause()) ?></td></tr>
|
<tr><th scope="row"><?php echo translate('Cause') ?></th><td><?php echo validHtmlStr($event->Cause()) ?></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('Notes') ?></th><td><?php echo validHtmlStr($event->Notes()) ?></td></tr>
|
<tr><th scope="row"><?php echo translate('Notes') ?></th><td><?php echo validHtmlStr($event->Notes()) ?></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td></tr>
|
<tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) ?></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('Duration') ?></th><td><?php echo $event->Length() ?></td></tr>
|
<tr><th scope="row"><?php echo translate('Duration') ?></th><td><?php echo $event->Length() ?></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('Frames') ?></th><td><?php echo $event->Frames() ?></td></tr>
|
<tr><th scope="row"><?php echo translate('Frames') ?></th><td><?php echo $event->Frames() ?></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('AttrAlarmFrames') ?></th><td><?php echo $event->AlarmFrames() ?></td></tr>
|
<tr><th scope="row"><?php echo translate('AttrAlarmFrames') ?></th><td><?php echo $event->AlarmFrames() ?></td></tr>
|
||||||
|
@ -999,5 +999,5 @@ function exportEvents(
|
||||||
unlink($monitorPath.'/'.$html_eventMaster);
|
unlink($monitorPath.'/'.$html_eventMaster);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '?view=archive%26type='.$exportFormat.'%26connkey='.$connkey;
|
return '?view=archive&type='.$exportFormat.'&connkey='.$connkey;
|
||||||
} // end function exportEvents
|
} // end function exportEvents
|
||||||
|
|
|
@ -497,16 +497,16 @@ function getBandwidthHTML($bandwidth_options, $user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = '<li id="getBandwidthHTML" class="nav-item dropdown mx-2">'.PHP_EOL;
|
$result = '<li id="getBandwidthHTML" class="nav-item dropdown mx-2">'.PHP_EOL;
|
||||||
$result .= '<a class="dropdown-toggle mr-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="material-icons md-18 mr-1">network_check</i>'.translate($bandwidth_options[$_COOKIE['zmBandwidth']]).'</a>'.PHP_EOL;
|
$result .= '<a class="dropdown-toggle mr-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdown_bandwidth"><i class="material-icons md-18 mr-1">network_check</i>'.translate($bandwidth_options[$_COOKIE['zmBandwidth']]).'</a>'.PHP_EOL;
|
||||||
|
|
||||||
$result .= '<div class="dropdown-menu" id="dropdown_bandwidth" aria-labelledby="dropdown_bandwidth">'.PHP_EOL;
|
$result .= '<div class="dropdown-menu" aria-labelledby="dropdown_bandwidth">'.PHP_EOL;
|
||||||
if ( count($bandwidth_options) > 1 ) {
|
if ( count($bandwidth_options) > 1 ) {
|
||||||
if ( isset($bandwidth_options['high']) )
|
if ( isset($bandwidth_options['high']) )
|
||||||
$result .= '<a data-pdsa-dropdown-val="high" class="dropdown-item" href="#">' .translate('High'). '</a>'.PHP_EOL;
|
$result .= '<a data-pdsa-dropdown-val="high" class="dropdown-item bwselect" href="#">' .translate('High'). '</a>'.PHP_EOL;
|
||||||
if ( isset($bandwidth_options['medium']) )
|
if ( isset($bandwidth_options['medium']) )
|
||||||
$result .= '<a data-pdsa-dropdown-val="medium" class="dropdown-item" href="#">' .translate('Medium'). '</a>'.PHP_EOL;
|
$result .= '<a data-pdsa-dropdown-val="medium" class="dropdown-item bwselect" href="#">' .translate('Medium'). '</a>'.PHP_EOL;
|
||||||
# low is theoretically always available
|
# low is theoretically always available
|
||||||
$result .= '<a data-pdsa-dropdown-val="low" class="dropdown-item" href="#">' .translate('Low'). '</a>'.PHP_EOL;
|
$result .= '<a data-pdsa-dropdown-val="low" class="dropdown-item bwselect" href="#">' .translate('Low'). '</a>'.PHP_EOL;
|
||||||
}
|
}
|
||||||
$result .= '</div>'.PHP_EOL;
|
$result .= '</div>'.PHP_EOL;
|
||||||
|
|
||||||
|
@ -871,8 +871,8 @@ function xhtmlFooter() {
|
||||||
<script src="tools/mootools/mootools-more.js"></script>
|
<script src="tools/mootools/mootools-more.js"></script>
|
||||||
<script src="js/mootools.ext.js"></script>
|
<script src="js/mootools.ext.js"></script>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<script src="skins/<?php echo $skin; ?>/js/jquery.js"></script>
|
<script src="skins/<?php echo $skin; ?>/js/jquery.min.js"></script>
|
||||||
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.js"></script>
|
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.min.js"></script>
|
||||||
<script src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
|
<script src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
|
||||||
<?php echo output_script_if_exists(array(
|
<?php echo output_script_if_exists(array(
|
||||||
'js/bootstrap-table.min.js',
|
'js/bootstrap-table.min.js',
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
jquery-2.2.4.js
|
|
|
@ -1 +0,0 @@
|
||||||
https://code.jquery.com/jquery-2.2.4.js
|
|
|
@ -0,0 +1 @@
|
||||||
|
jquery-3.5.1.min.js
|
|
@ -0,0 +1 @@
|
||||||
|
https://code.jquery.com/jquery-3.5.1.min.js
|
|
@ -241,7 +241,7 @@ if ( currentView != 'none' && currentView != 'login' ) {
|
||||||
$j(document).ready(function() {
|
$j(document).ready(function() {
|
||||||
// Load the Logout and State modals into the dom
|
// Load the Logout and State modals into the dom
|
||||||
$j('#logoutButton').click(clickLogout);
|
$j('#logoutButton').click(clickLogout);
|
||||||
if ( canEditSystem ) $j('#stateModalBtn').click(getStateModal);
|
if ( canEdit.System ) $j('#stateModalBtn').click(getStateModal);
|
||||||
|
|
||||||
// Trigger autorefresh of the widget bar stats on the navbar
|
// Trigger autorefresh of the widget bar stats on the navbar
|
||||||
if ( $j('.navbar').length ) {
|
if ( $j('.navbar').length ) {
|
||||||
|
@ -639,7 +639,7 @@ function delCookie(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function bwClickFunction() {
|
function bwClickFunction() {
|
||||||
$j("#dropdown_bandwidth a").click(function() {
|
$j('.bwselect').click(function() {
|
||||||
var bwval = $j(this).data('pdsa-dropdown-val');
|
var bwval = $j(this).data('pdsa-dropdown-val');
|
||||||
setCookie("zmBandwidth", bwval, 3600);
|
setCookie("zmBandwidth", bwval, 3600);
|
||||||
getNavBar();
|
getNavBar();
|
||||||
|
@ -830,10 +830,11 @@ function startDownload( exportFile ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportResponse(data, responseText) {
|
function exportResponse(data, responseText) {
|
||||||
console.log(data);
|
console.log('exportResponse data: ' + JSON.stringify(data));
|
||||||
|
|
||||||
var generated = (data.result=='Ok') ? 1 : 0;
|
var generated = (data.result=='Ok') ? 1 : 0;
|
||||||
var exportFile = '?view=archive&type='+data.exportFormat+'&connkey='+data.connkey;
|
//var exportFile = '?view=archive&type='+data.exportFormat+'&connkey='+data.connkey;
|
||||||
|
var exportFile = data.exportFile;
|
||||||
|
|
||||||
$j('#exportProgress').removeClass( 'text-warning' );
|
$j('#exportProgress').removeClass( 'text-warning' );
|
||||||
if ( generated ) {
|
if ( generated ) {
|
||||||
|
@ -888,3 +889,33 @@ function manageShutdownBtns(element) {
|
||||||
})
|
})
|
||||||
.fail(logAjaxFail);
|
.fail(logAjaxFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function thumbnail_onmouseover(event) {
|
||||||
|
timeout = setTimeout(function() {
|
||||||
|
var img = event.target;
|
||||||
|
var imgClass = ( currentView == 'console' ) ? 'zoom-console' : 'zoom';
|
||||||
|
var imgAttr = ( currentView == 'frames' ) ? 'full_img_src' : 'stream_src';
|
||||||
|
img.src = '';
|
||||||
|
img.src = img.getAttribute(imgAttr);
|
||||||
|
img.addClass(imgClass);
|
||||||
|
}, 350);
|
||||||
|
}
|
||||||
|
|
||||||
|
function thumbnail_onmouseout(event) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
var img = event.target;
|
||||||
|
var imgClass = ( currentView == 'console' ) ? 'zoom-console' : 'zoom';
|
||||||
|
var imgAttr = ( currentView == 'frames' ) ? 'img_src' : 'still_src';
|
||||||
|
img.src = '';
|
||||||
|
img.src = img.getAttribute(imgAttr);
|
||||||
|
img.removeClass(imgClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initThumbAnimation() {
|
||||||
|
if ( ANIMATE_THUMBS ) {
|
||||||
|
$j('.colThumbnail img').each(function() {
|
||||||
|
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
||||||
|
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -40,14 +40,19 @@ var thisUrl = '<?php echo ZM_BASE_URL.preg_replace('/\.php.*$/i', '.php', $_SERV
|
||||||
var skinPath = '<?php echo ZM_SKIN_PATH ?>';
|
var skinPath = '<?php echo ZM_SKIN_PATH ?>';
|
||||||
var serverId = '<?php echo defined('ZM_SERVER_ID') ? ZM_SERVER_ID : '' ?>';
|
var serverId = '<?php echo defined('ZM_SERVER_ID') ? ZM_SERVER_ID : '' ?>';
|
||||||
|
|
||||||
var canEditSystem = <?php echo canEdit('System')?'true':'false' ?>;
|
var canView = {};
|
||||||
var canViewSystem = <?php echo canView('System')?'true':'false' ?>;
|
var canEdit = {};
|
||||||
var canEditEvents = <?php echo canEdit('Events')?'true':'false' ?>;
|
<?php
|
||||||
var canViewEvents = <?php echo canView('Events')?'true':'false' ?>;
|
$perms = array("Stream", "Events", "Control", "Monitors", "Groups", "System", "Devices");
|
||||||
var canEditMonitors = <?php echo canEdit('Monitors')?'true':'false' ?>;
|
foreach ( $perms as $perm ) {
|
||||||
var canViewMonitors = <?php echo canView('Monitors')?'true':'false' ?>;
|
?>
|
||||||
|
canView["<?php echo $perm ?>"] = <?php echo canView($perm)?'true':'false' ?>;
|
||||||
|
canEdit["<?php echo $perm ?>"] = <?php echo canEdit($perm)?'true':'false' ?>;
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
var canEditGroups = <?php echo canEdit('Groups')?'true':'false' ?>;
|
var ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
||||||
|
|
||||||
var refreshParent = <?php
|
var refreshParent = <?php
|
||||||
if ( ! empty($refreshParent) ) {
|
if ( ! empty($refreshParent) ) {
|
||||||
|
|
|
@ -82,10 +82,10 @@ if ( $groupSql )
|
||||||
foreach ( array('ServerId','StorageId','Status','Function') as $filter ) {
|
foreach ( array('ServerId','StorageId','Status','Function') as $filter ) {
|
||||||
if ( isset($_SESSION[$filter]) ) {
|
if ( isset($_SESSION[$filter]) ) {
|
||||||
if ( is_array($_SESSION[$filter]) ) {
|
if ( is_array($_SESSION[$filter]) ) {
|
||||||
$conditions[] = $filter . ' IN ('.implode(',', array_map(function(){return '?';}, $_SESSION[$filter])). ')';
|
$conditions[] = '`'.$filter . '` IN ('.implode(',', array_map(function(){return '?';}, $_SESSION[$filter])). ')';
|
||||||
$values = array_merge($values, $_SESSION[$filter]);
|
$values = array_merge($values, $_SESSION[$filter]);
|
||||||
} else {
|
} else {
|
||||||
$conditions[] = $filter . '=?';
|
$conditions[] = '`'.$filter . '`=?';
|
||||||
$values[] = $_SESSION[$filter];
|
$values[] = $_SESSION[$filter];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,9 +248,9 @@ $html .= '</span>
|
||||||
'multiple'=>'multiple',
|
'multiple'=>'multiple',
|
||||||
'data-placeholder'=>'All',
|
'data-placeholder'=>'All',
|
||||||
) );
|
) );
|
||||||
# Repurpose this variable to be the list of MonitorIds as a result of all the filtering
|
# Repurpose this variable to be the list of MonitorIds as a result of all the filtering
|
||||||
$selected_monitor_ids = array_map(function($monitor_row){return $monitor_row['Id'];}, $displayMonitors);
|
$selected_monitor_ids = array_map(function($monitor_row){return $monitor_row['Id'];}, $displayMonitors);
|
||||||
$html .= '</span>
|
$html .= '</span>
|
||||||
';
|
';
|
||||||
echo $html;
|
echo $html;
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -296,7 +296,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
$imgHTML='';
|
$imgHTML='';
|
||||||
if ( ZM_WEB_LIST_THUMBS && ($monitor['Status'] == 'Connected') && $running ) {
|
if ( ZM_WEB_LIST_THUMBS && ($monitor['Status'] == 'Connected') && $running ) {
|
||||||
$options = array();
|
$options = array();
|
||||||
$thmbClass = ZM_WEB_ANIMATE_THUMBS ? 'colThumbnail zoom-right' : 'colThumbnail';
|
|
||||||
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
||||||
$options['width'] = ZM_WEB_LIST_THUMB_WIDTH;
|
$options['width'] = ZM_WEB_LIST_THUMB_WIDTH;
|
||||||
$options['height'] = ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor;
|
$options['height'] = ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor;
|
||||||
|
@ -309,7 +309,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
$thmbWidth = ( $options['width'] ) ? 'width:'.$options['width'].'px;' : '';
|
$thmbWidth = ( $options['width'] ) ? 'width:'.$options['width'].'px;' : '';
|
||||||
$thmbHeight = ( $options['height'] ) ? 'height:'.$options['height'].'px;' : '';
|
$thmbHeight = ( $options['height'] ) ? 'height:'.$options['height'].'px;' : '';
|
||||||
|
|
||||||
$imgHTML = '<div class="'.$thmbClass.'"><a';
|
$imgHTML = '<div class="colThumbnail"><a';
|
||||||
$imgHTML .= $stream_available ? ' href="?view=watch&mid='.$monitor['Id'].'">' : '>';
|
$imgHTML .= $stream_available ? ' href="?view=watch&mid='.$monitor['Id'].'">' : '>';
|
||||||
$imgHTML .= '<img id="thumbnail' .$Monitor->Id(). '" src="' .$stillSrc. '" style="'
|
$imgHTML .= '<img id="thumbnail' .$Monitor->Id(). '" src="' .$stillSrc. '" style="'
|
||||||
.$thmbWidth.$thmbHeight. '" stream_src="' .$streamSrc. '" still_src="' .$stillSrc. '"'.
|
.$thmbWidth.$thmbHeight. '" stream_src="' .$streamSrc. '" still_src="' .$stillSrc. '"'.
|
||||||
|
|
|
@ -42,7 +42,7 @@ xhtmlHeaders(__FILE__, translate('ControlCaps'));
|
||||||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content" class="table-responsive-sm">
|
||||||
<table
|
<table
|
||||||
id="controlTable"
|
id="controlTable"
|
||||||
data-locale="<?php echo i18n() ?>"
|
data-locale="<?php echo i18n() ?>"
|
||||||
|
@ -54,7 +54,6 @@ xhtmlHeaders(__FILE__, translate('ControlCaps'));
|
||||||
data-remember-order="true"
|
data-remember-order="true"
|
||||||
data-click-to-select="true"
|
data-click-to-select="true"
|
||||||
data-maintain-meta-data="true"
|
data-maintain-meta-data="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-toolbar="#toolbar"
|
data-toolbar="#toolbar"
|
||||||
data-show-columns="true"
|
data-show-columns="true"
|
||||||
|
|
|
@ -46,7 +46,7 @@ xhtmlHeaders(__FILE__, translate('Devices') );
|
||||||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="content" class="row justify-content-center">
|
<div id="content" class="row justify-content-center table-responsive-sm">
|
||||||
<table
|
<table
|
||||||
id="devicesTable"
|
id="devicesTable"
|
||||||
data-locale="<?php echo i18n() ?>"
|
data-locale="<?php echo i18n() ?>"
|
||||||
|
@ -59,7 +59,6 @@ xhtmlHeaders(__FILE__, translate('Devices') );
|
||||||
data-remember-order="true"
|
data-remember-order="true"
|
||||||
data-click-to-select="true"
|
data-click-to-select="true"
|
||||||
data-maintain-meta-data="true"
|
data-maintain-meta-data="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-toolbar="#toolbar"
|
data-toolbar="#toolbar"
|
||||||
data-show-columns="true"
|
data-show-columns="true"
|
||||||
|
|
|
@ -131,8 +131,6 @@ if ( !$Event->Id() ) {
|
||||||
} else {
|
} else {
|
||||||
if ( !file_exists($Event->Path()) )
|
if ( !file_exists($Event->Path()) )
|
||||||
echo '<div class="error">Event was not found at '.$Event->Path().'. It is unlikely that playback will be possible.</div>';
|
echo '<div class="error">Event was not found at '.$Event->Path().'. It is unlikely that playback will be possible.</div>';
|
||||||
|
|
||||||
$storage = validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' );
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- BEGIN HEADER -->
|
<!-- BEGIN HEADER -->
|
||||||
|
@ -164,64 +162,7 @@ if ( !$Event->Id() ) {
|
||||||
<div class="">
|
<div class="">
|
||||||
<!-- VIDEO STATISTICS TABLE -->
|
<!-- VIDEO STATISTICS TABLE -->
|
||||||
<table id="eventStatsTable" class="table-sm table-borderless">
|
<table id="eventStatsTable" class="table-sm table-borderless">
|
||||||
<tbody>
|
<!-- EVENT STATISTICS POPULATED BY JAVASCRIPT -->
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('EventId') ?></th>
|
|
||||||
<td id="dataEventId"><?php echo $Event->Id() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('EventName') ?></th>
|
|
||||||
<td id="dataEventName"><?php echo $Event->Name() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrMonitorId') ?></th>
|
|
||||||
<td id="dataMonitorId"><?php echo $Monitor->Id() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrMonitorName') ?></th>
|
|
||||||
<td id="dataMonitorName"><?php echo validHtmlStr($Monitor->Name()) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('Cause') ?></th>
|
|
||||||
<td id="dataCause"><?php echo validHtmlStr($Event->Cause()) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrStartTime') ?></th>
|
|
||||||
<td id="dataStartTime"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('Duration') ?></th>
|
|
||||||
<td id="dataDuration"><?php echo $Event->Length().'s' ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrFrames') ?></th>
|
|
||||||
<td id="dataFrames"><?php echo $Event->Frames() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrAlarmFrames') ?></th>
|
|
||||||
<td id="dataAlarmFrames"><?php echo $Event->AlarmFrames() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrTotalScore') ?></th>
|
|
||||||
<td id="dataTotalScore"><?php echo $Event->TotScore() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrAvgScore') ?></th>
|
|
||||||
<td id="dataAvgScore"><?php echo $Event->AvgScore() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('AttrMaxScore') ?></th>
|
|
||||||
<td id="dataMaxScore"><?php echo $Event->MaxScore() ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('DiskSpace') ?></th>
|
|
||||||
<td id="dataDiskSpace"><?php echo human_filesize($Event->DiskSpace(null)) ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right"><?php echo translate('Storage') ?></th>
|
|
||||||
<td id="dataStorage"><?php echo $storage?></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
|
|
|
@ -87,7 +87,6 @@ getBodyTopHTML();
|
||||||
data-show-fullscreen="true"
|
data-show-fullscreen="true"
|
||||||
data-click-to-select="true"
|
data-click-to-select="true"
|
||||||
data-maintain-meta-data="true"
|
data-maintain-meta-data="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-show-jump-to="true"
|
data-show-jump-to="true"
|
||||||
data-show-refresh="true"
|
data-show-refresh="true"
|
||||||
|
|
|
@ -143,21 +143,21 @@ $event_count = 0;
|
||||||
while ( $event_row = dbFetchNext($results) ) {
|
while ( $event_row = dbFetchNext($results) ) {
|
||||||
$event = new ZM\Event($event_row);
|
$event = new ZM\Event($event_row);
|
||||||
$scale = max(reScale(SCALE_BASE, $event->Monitor()->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
|
$scale = max(reScale(SCALE_BASE, $event->Monitor()->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
|
||||||
|
$event_link = '?view=event&eid='.$event->Id().$filterQuery.$sortQuery.'&page=1';
|
||||||
?>
|
?>
|
||||||
<tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>>
|
<tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>>
|
||||||
<td class="colId">
|
<td class="colId">
|
||||||
<input type="hidden" name="eids[]" value="<?php echo $event->Id()?>"/>
|
<input type="hidden" name="eids[]" value="<?php echo $event->Id()?>"/>
|
||||||
<a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery ?>&page=1"><?php echo $event->Id().($event->Archived()?'*':'') ?></a>
|
<a href="<?php echo $event_link ?>"><?php echo $event->Id().($event->Archived()?'*':'') ?></a>
|
||||||
</td>
|
</td>
|
||||||
<td class="colName"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery ?>&page=1"><?php echo validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
<td class="colName"><a href="<?php echo $event_link ?>"><?php echo validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
||||||
<td class="colMonitorName"><?php echo makeLink( '?view=monitor&mid='.$event->MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
|
<td class="colMonitorName"><?php echo makeLink('?view=monitor&mid='.$event->MonitorId(), $event->MonitorName(), canEdit('Monitors')) ?></td>
|
||||||
<td class="colCause"><?php echo makeLink( '#', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?></td>
|
<td class="colCause"><?php echo makeLink($event_link, validHtmlStr($event->Cause()), canView('Events'), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid="'.$event->Id().'"') ?></td>
|
||||||
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) .
|
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) .
|
||||||
( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime()) ) : '' ) ?>
|
( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime())) : '' ) ?></td>
|
||||||
</td>
|
<td class="colDuration"><?php echo gmdate('H:i:s', $event->Length()) ?></td>
|
||||||
<td class="colDuration"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
|
<td class="colFrames"><?php echo makeLink('?view=frames&eid='.$event->Id(), $event->Frames()) ?></td>
|
||||||
<td class="colFrames"><?php echo makeLink( '?view=frames&eid='.$event->Id(), $event->Frames() ) ?></td>
|
<td class="colAlarmFrames"><?php echo makeLink('?view=frames&eid='.$event->Id(), $event->AlarmFrames()) ?></td>
|
||||||
<td class="colAlarmFrames"><?php echo makeLink( '?view=frames&eid='.$event->Id(), $event->AlarmFrames() ) ?></td>
|
|
||||||
<td class="colTotScore"><?php echo $event->TotScore() ?></td>
|
<td class="colTotScore"><?php echo $event->TotScore() ?></td>
|
||||||
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
|
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
|
||||||
<td class="colMaxScore"><?php echo $event->MaxScore() ?></td>
|
<td class="colMaxScore"><?php echo $event->MaxScore() ?></td>
|
||||||
|
@ -168,9 +168,7 @@ while ( $event_row = dbFetchNext($results) ) {
|
||||||
echo '<td class="colDiskSpace">'.human_filesize($event->DiskSpace()).'</td>';
|
echo '<td class="colDiskSpace">'.human_filesize($event->DiskSpace()).'</td>';
|
||||||
}
|
}
|
||||||
unset($event);
|
unset($event);
|
||||||
echo '
|
echo PHP_EOL.'</tr>'.PHP_EOL;
|
||||||
</tr>
|
|
||||||
';
|
|
||||||
} # end foreach event
|
} # end foreach event
|
||||||
?>
|
?>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -179,9 +177,7 @@ while ( $event_row = dbFetchNext($results) ) {
|
||||||
<td colspan="11"><?php echo $event_count ?> events</td>
|
<td colspan="11"><?php echo $event_count ?> events</td>
|
||||||
<?php
|
<?php
|
||||||
if ( ZM_WEB_EVENT_DISK_SPACE ) {
|
if ( ZM_WEB_EVENT_DISK_SPACE ) {
|
||||||
?>
|
echo '<td class="colDiskSpace">'.human_filesize($disk_space_total).'</td>'.PHP_EOL;
|
||||||
<td class="colDiskSpace"><?php echo human_filesize($disk_space_total);?></td>
|
|
||||||
<?php
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -49,7 +49,7 @@ $prevFid = $fid-1;
|
||||||
$nextFid = $fid+1;
|
$nextFid = $fid+1;
|
||||||
$lastFid = $maxFid;
|
$lastFid = $maxFid;
|
||||||
|
|
||||||
$alarmFrame = $Frame->Type() == 'Alarm';
|
$alarmFrame = ( $Frame->Type() == 'Alarm' ) ? 1 : 0;
|
||||||
|
|
||||||
if ( isset($_REQUEST['scale']) ) {
|
if ( isset($_REQUEST['scale']) ) {
|
||||||
$scale = validNum($_REQUEST['scale']);
|
$scale = validNum($_REQUEST['scale']);
|
||||||
|
@ -103,7 +103,14 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id().' - '.$Frame->Frame
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content" class="d-flex flex-row justify-content-center">
|
||||||
|
|
||||||
|
|
||||||
|
<table id="frameStatsTable" class="table-sm table-borderless pr-3">
|
||||||
|
<!-- FRAME STATISTICS POPULATED BY AJAX -->
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div>
|
||||||
<p id="image">
|
<p id="image">
|
||||||
<?php if ( $imageData['hasAnalImage'] ) {
|
<?php if ( $imageData['hasAnalImage'] ) {
|
||||||
echo sprintf('<a href="?view=frame&eid=%d&fid=%d&scale=%d&show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
|
echo sprintf('<a href="?view=frame&eid=%d&fid=%d&scale=%d&show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
|
||||||
|
@ -152,6 +159,7 @@ if ( file_exists($rImagePath) ) {
|
||||||
class="<?php echo $imageData['imageClass'] ?>"
|
class="<?php echo $imageData['imageClass'] ?>"
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -41,7 +41,7 @@ xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Table styling handled by bootstrap-tables -->
|
<!-- Table styling handled by bootstrap-tables -->
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center table-responsive-sm">
|
||||||
<table
|
<table
|
||||||
id="framesTable"
|
id="framesTable"
|
||||||
data-locale="<?php echo i18n() ?>"
|
data-locale="<?php echo i18n() ?>"
|
||||||
|
@ -60,7 +60,6 @@ xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
|
||||||
data-toolbar="#toolbar"
|
data-toolbar="#toolbar"
|
||||||
data-show-fullscreen="true"
|
data-show-fullscreen="true"
|
||||||
data-maintain-meta-data="true"
|
data-maintain-meta-data="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-detail-view="true"
|
data-detail-view="true"
|
||||||
data-detail-formatter="detailFormatter"
|
data-detail-formatter="detailFormatter"
|
||||||
|
|
|
@ -1,24 +1,3 @@
|
||||||
function thumbnail_onmouseover(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('stream_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function thumbnail_onmouseout(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('still_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function initThumbAnimation() {
|
|
||||||
if ( WEB_ANIMATE_THUMBS ) {
|
|
||||||
$j('.colThumbnail img').each(function() {
|
|
||||||
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
|
||||||
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setButtonStates( element ) {
|
function setButtonStates( element ) {
|
||||||
var form = element.form;
|
var form = element.form;
|
||||||
var checked = 0;
|
var checked = 0;
|
||||||
|
@ -133,7 +112,7 @@ function reloadWindow() {
|
||||||
function manageFunctionModal(evt) {
|
function manageFunctionModal(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
if ( !canEditEvents ) {
|
if ( !canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -172,8 +151,25 @@ function manageFunctionModal(evt) {
|
||||||
console.error("Unable to find form with id function_form");
|
console.error("Unable to find form with id function_form");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
function_form.elements['newFunction'].onchange=function() {
|
||||||
|
$j('#function_help div').hide();
|
||||||
|
$j('#'+this.value+'Help').show();
|
||||||
|
if ( this.value == 'Monitor' || this.value == 'None' ) {
|
||||||
|
$j('#FunctionAnalysisEnabled').hide();
|
||||||
|
} else {
|
||||||
|
$j('#FunctionAnalysisEnabled').show();
|
||||||
|
}
|
||||||
|
if ( this.value == 'Record' || this.value == 'Nodect' ) {
|
||||||
|
$j('#FunctionDecodingEnabled').show();
|
||||||
|
} else {
|
||||||
|
$j('#FunctionDecodingEnabled').hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
function_form.elements['newFunction'].value = monitor.Function;
|
function_form.elements['newFunction'].value = monitor.Function;
|
||||||
|
function_form.elements['newFunction'].onchange();
|
||||||
|
|
||||||
function_form.elements['newEnabled'].checked = monitor.Enabled == '1';
|
function_form.elements['newEnabled'].checked = monitor.Enabled == '1';
|
||||||
|
function_form.elements['newDecodingEnabled'].checked = monitor.DecodingEnabled == '1';
|
||||||
function_form.elements['mid'].value = mid;
|
function_form.elements['mid'].value = mid;
|
||||||
document.getElementById('function_monitor_name').innerHTML = monitor.Name;
|
document.getElementById('function_monitor_name').innerHTML = monitor.Name;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
var consoleRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_MAIN ?>;
|
var consoleRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_MAIN ?>;
|
||||||
var WEB_ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if ( canEdit('System') && ZM_DYN_SHOW_DONATE_REMINDER ) {
|
if ( canEdit('System') && ZM_DYN_SHOW_DONATE_REMINDER ) {
|
||||||
|
@ -25,7 +24,8 @@ var monitors = new Array();
|
||||||
'Url': '<?php echo $monitor->UrlToIndex( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
'Url': '<?php echo $monitor->UrlToIndex( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||||
'Type': '<?php echo $monitor->Type() ?>',
|
'Type': '<?php echo $monitor->Type() ?>',
|
||||||
'Function': '<?php echo $monitor->Function() ?>',
|
'Function': '<?php echo $monitor->Function() ?>',
|
||||||
'Enabled': '<?php echo $monitor->Enabled() ?>'
|
'Enabled': '<?php echo $monitor->Enabled() ?>',
|
||||||
|
'DecodingEnabled': '<?php echo $monitor->DecodingEnabled() ?>'
|
||||||
};
|
};
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ function getDelConfirmModal(key) {
|
||||||
// Manage the DELETE CONFIRMATION modal button
|
// Manage the DELETE CONFIRMATION modal button
|
||||||
function manageDelConfirmModalBtns() {
|
function manageDelConfirmModalBtns() {
|
||||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||||
if ( ! canEditControl ) {
|
if ( ! canEdit.Control ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,9 @@ function initPage() {
|
||||||
function() {
|
function() {
|
||||||
selections = table.bootstrapTable('getSelections');
|
selections = table.bootstrapTable('getSelections');
|
||||||
|
|
||||||
addNewBtn.prop('disabled', (selections.length || !canEditControl));
|
addNewBtn.prop('disabled', (selections.length || !canEdit.Control));
|
||||||
editBtn.prop('disabled', !((selections.length == 1) && canEditControl));
|
editBtn.prop('disabled', !((selections.length == 1) && canEdit.Control));
|
||||||
deleteBtn.prop('disabled', !(selections.length && canEditControl));
|
deleteBtn.prop('disabled', !(selections.length && canEdit.Control));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Init the bootstrap-table
|
// Init the bootstrap-table
|
||||||
|
@ -92,7 +92,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the DELETE button
|
// Manage the DELETE button
|
||||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||||
if ( ! canEditControl ) {
|
if ( ! canEdit.Control ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
var canEditControl = <?php echo canEdit('Control')?'true':'false' ?>;
|
|
|
@ -42,7 +42,7 @@ function getDelConfirmModal(key) {
|
||||||
// Manage the DELETE CONFIRMATION modal button
|
// Manage the DELETE CONFIRMATION modal button
|
||||||
function manageDelConfirmModalBtns() {
|
function manageDelConfirmModalBtns() {
|
||||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||||
if ( ! canEditDevice ) {
|
if ( ! canEdit.Device ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,9 @@ function initPage() {
|
||||||
// Init the bootstrap-table
|
// Init the bootstrap-table
|
||||||
table.bootstrapTable({icons: icons});
|
table.bootstrapTable({icons: icons});
|
||||||
|
|
||||||
if ( canEditDevice ) enableDeviceModal();
|
if ( canEdit.Device ) enableDeviceModal();
|
||||||
|
|
||||||
newDeviceBtn.prop('disabled', !canEditDevice);
|
newDeviceBtn.prop('disabled', !canEdit.Device);
|
||||||
|
|
||||||
// Manage the BACK button
|
// Manage the BACK button
|
||||||
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
|
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
|
||||||
|
@ -112,7 +112,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the DELETE button
|
// Manage the DELETE button
|
||||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||||
if ( ! canEditDevice ) {
|
if ( ! canEdit.Device ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ function initPage() {
|
||||||
function() {
|
function() {
|
||||||
selections = table.bootstrapTable('getSelections');
|
selections = table.bootstrapTable('getSelections');
|
||||||
|
|
||||||
deleteBtn.prop('disabled', !(selections.length && canEditDevice));
|
deleteBtn.prop('disabled', !(selections.length && canEdit.Device));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Process mouse clicks on the table cells
|
// Process mouse clicks on the table cells
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
var canEditDevice = <?php echo canEdit('Devices') ? 'true' : 'false' ?>;
|
|
|
@ -598,8 +598,8 @@ function getEventResponse(respObj, respText) {
|
||||||
$j('dataStorage').text( eventData.Storage );
|
$j('dataStorage').text( eventData.Storage );
|
||||||
|
|
||||||
// Refresh the status of the archive buttons
|
// Refresh the status of the archive buttons
|
||||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
archiveBtn.prop('disabled', !(!eventData.Archived && canEdit.Events));
|
||||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||||
|
|
||||||
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery); //if popup removed, check if this allows forward
|
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery); //if popup removed, check if this allows forward
|
||||||
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
|
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
|
||||||
|
@ -1032,20 +1032,10 @@ function handleClick( event ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the Delete Confirmation Modal HTML via Ajax call
|
|
||||||
function getDelConfirmModal() {
|
|
||||||
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm')
|
|
||||||
.done(function(data) {
|
|
||||||
insertModalHtml('deleteConfirm', data.html);
|
|
||||||
manageDelConfirmModalBtns();
|
|
||||||
})
|
|
||||||
.fail(logAjaxFail);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manage the DELETE CONFIRMATION modal button
|
// Manage the DELETE CONFIRMATION modal button
|
||||||
function manageDelConfirmModalBtns() {
|
function manageDelConfirmModalBtns() {
|
||||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1065,22 +1055,34 @@ function manageDelConfirmModalBtns() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEvtStatsCookie() {
|
function getEvtStatsCookie() {
|
||||||
var cookie = 'zmEventStats'
|
var cookie = 'zmEventStats';
|
||||||
var stats = getCookie(cookie);
|
var stats = getCookie(cookie);
|
||||||
|
|
||||||
if ( !stats ) {
|
if ( !stats ) {
|
||||||
stats = 'on'
|
stats = 'on';
|
||||||
setCookie(cookie, stats, 10*365);
|
setCookie(cookie, stats, 10*365);
|
||||||
}
|
}
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStat() {
|
||||||
|
table.empty().append('<tbody>');
|
||||||
|
$j.each( eventDataStrings, function( key ) {
|
||||||
|
var th = $j('<th>').addClass('text-right').text(eventDataStrings[key]);
|
||||||
|
var tdString = ( eventData[key].length ) ? eventData[key] : 'n/a';
|
||||||
|
var td = $j('<td>').text(tdString);
|
||||||
|
var row = $j('<tr>').append(th, td);
|
||||||
|
|
||||||
|
$j('#eventStatsTable tbody').append(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initPage() {
|
function initPage() {
|
||||||
// Load the delete confirmation modal into the DOM
|
// Load the event stats
|
||||||
getDelConfirmModal();
|
getStat();
|
||||||
|
|
||||||
var stats = getEvtStatsCookie();
|
var stats = getEvtStatsCookie();
|
||||||
if ( stats != 'on' ) table.toggle(false)
|
if ( stats != 'on' ) table.toggle(false);
|
||||||
|
|
||||||
//FIXME prevent blocking...not sure what is happening or best way to unblock
|
//FIXME prevent blocking...not sure what is happening or best way to unblock
|
||||||
if ( $j('#videoobj').length ) {
|
if ( $j('#videoobj').length ) {
|
||||||
|
@ -1134,13 +1136,13 @@ function initPage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// enable or disable buttons based on current selection and user rights
|
// enable or disable buttons based on current selection and user rights
|
||||||
renameBtn.prop('disabled', !canEditEvents);
|
renameBtn.prop('disabled', !canEdit.Events);
|
||||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
archiveBtn.prop('disabled', !(!eventData.Archived && canEdit.Events));
|
||||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||||
editBtn.prop('disabled', !canEditEvents);
|
editBtn.prop('disabled', !canEdit.Events);
|
||||||
exportBtn.prop('disabled', !canViewEvents);
|
exportBtn.prop('disabled', !canView.Events);
|
||||||
downloadBtn.prop('disabled', !canViewEvents);
|
downloadBtn.prop('disabled', !canView.Events);
|
||||||
deleteBtn.prop('disabled', !canEditEvents);
|
deleteBtn.prop('disabled', !canEdit.Events);
|
||||||
|
|
||||||
// Don't enable the back button if there is no previous zm page to go back to
|
// Don't enable the back button if there is no previous zm page to go back to
|
||||||
backBtn.prop('disabled', !document.referrer.length);
|
backBtn.prop('disabled', !document.referrer.length);
|
||||||
|
@ -1183,7 +1185,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the UNARCHIVE button
|
// Manage the UNARCHIVE button
|
||||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1200,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the EDIT button
|
// Manage the EDIT button
|
||||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1239,7 +1241,7 @@ function initPage() {
|
||||||
// Manage the Event STATISTICS Button
|
// Manage the Event STATISTICS Button
|
||||||
document.getElementById("statsBtn").addEventListener("click", function onStatsClick(evt) {
|
document.getElementById("statsBtn").addEventListener("click", function onStatsClick(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
var cookie = 'zmEventStats'
|
var cookie = 'zmEventStats';
|
||||||
|
|
||||||
// Toggle the visiblity of the stats table and write an appropriate cookie
|
// Toggle the visiblity of the stats table and write an appropriate cookie
|
||||||
if ( table.is(':visible') ) {
|
if ( table.is(':visible') ) {
|
||||||
|
@ -1247,18 +1249,29 @@ function initPage() {
|
||||||
table.toggle(false);
|
table.toggle(false);
|
||||||
} else {
|
} else {
|
||||||
setCookie(cookie, 'on', 10*365);
|
setCookie(cookie, 'on', 10*365);
|
||||||
table.toggle(true);
|
table.toggle(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Manage the DELETE button
|
// Manage the DELETE button
|
||||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
if ( ! $j('#deleteConfirm').length ) {
|
||||||
|
// Load the delete confirmation modal into the DOM
|
||||||
|
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm')
|
||||||
|
.done(function(data) {
|
||||||
|
insertModalHtml('deleteConfirm', data.html);
|
||||||
|
manageDelConfirmModalBtns();
|
||||||
|
$j('#deleteConfirm').modal('show');
|
||||||
|
})
|
||||||
|
.fail(logAjaxFail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
$j('#deleteConfirm').modal('show');
|
$j('#deleteConfirm').modal('show');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,17 +42,46 @@ var eventData = {
|
||||||
Id: '<?php echo $Event->Id() ?>',
|
Id: '<?php echo $Event->Id() ?>',
|
||||||
Name: '<?php echo $Event->Name() ?>',
|
Name: '<?php echo $Event->Name() ?>',
|
||||||
MonitorId: '<?php echo $Event->MonitorId() ?>',
|
MonitorId: '<?php echo $Event->MonitorId() ?>',
|
||||||
|
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>',
|
||||||
|
Cause: '<?php echo validHtmlStr($Event->Cause()) ?>',
|
||||||
Width: '<?php echo $Event->Width() ?>',
|
Width: '<?php echo $Event->Width() ?>',
|
||||||
Height: '<?php echo $Event->Height() ?>',
|
Height: '<?php echo $Event->Height() ?>',
|
||||||
Length: '<?php echo $Event->Length() ?>',
|
Length: '<?php echo $Event->Length() ?>',
|
||||||
StartDateTime: '<?php echo $Event->StartDateTime() ?>',
|
StartDateTime: '<?php echo $Event->StartDateTime() ?>',
|
||||||
|
StartDateTimeFmt: '<?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?>',
|
||||||
EndDateTime: '<?php echo $Event->EndDateTime() ?>',
|
EndDateTime: '<?php echo $Event->EndDateTime() ?>',
|
||||||
Frames: '<?php echo $Event->Frames() ?>',
|
Frames: '<?php echo $Event->Frames() ?>',
|
||||||
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>',
|
AlarmFrames: '<?php echo $Event->AlarmFrames() ?>',
|
||||||
|
TotScore: '<?php echo $Event->TotScore() ?>',
|
||||||
|
AvgScore: '<?php echo $Event->AvgScore() ?>',
|
||||||
|
MaxScore: '<?php echo $Event->MaxScore() ?>',
|
||||||
DiskSpace: '<?php echo human_filesize($Event->DiskSpace(null)) ?>',
|
DiskSpace: '<?php echo human_filesize($Event->DiskSpace(null)) ?>',
|
||||||
Storage: '<?php validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>',
|
Storage: '<?php echo validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>',
|
||||||
Archived: <?php echo $Event->Archived?'true':'false' ?>
|
ArchivedStr: '<?php echo $Event->Archived ? translate('Yes') : translate('No') ?>',
|
||||||
|
EmailedStr: '<?php echo $Event->Emailed ? translate('Yes') : translate('No') ?>',
|
||||||
|
Archived: <?php echo $Event->Archived?'true':'false' ?>,
|
||||||
|
Emailed: <?php echo $Event->Emailed?'true':'false' ?>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var eventDataStrings = {
|
||||||
|
Id: '<?php echo translate('EventId') ?>',
|
||||||
|
Name: '<?php echo translate('EventName') ?>',
|
||||||
|
MonitorId: '<?php echo translate('AttrMonitorId') ?>',
|
||||||
|
MonitorName: '<?php echo translate('AttrMonitorName') ?>',
|
||||||
|
Cause: '<?php echo translate('Cause') ?>',
|
||||||
|
StartDateTimeFmt: '<?php echo translate('AttrStartTime') ?>',
|
||||||
|
Length: '<?php echo translate('Duration') ?>',
|
||||||
|
Frames: '<?php echo translate('AttrFrames') ?>',
|
||||||
|
AlarmFrames: '<?php echo translate('AttrAlarmFrames') ?>',
|
||||||
|
TotScore: '<?php echo translate('AttrTotalScore') ?>',
|
||||||
|
AvgScore: '<?php echo translate('AttrAvgScore') ?>',
|
||||||
|
MaxScore: '<?php echo translate('AttrMaxScore') ?>',
|
||||||
|
DiskSpace: '<?php echo translate('DiskSpace') ?>',
|
||||||
|
Storage: '<?php echo translate('Storage') ?>',
|
||||||
|
ArchivedStr: '<?php echo translate('Archived') ?>',
|
||||||
|
EmailedStr: '<?php echo translate('Emailed') ?>'
|
||||||
|
};
|
||||||
|
|
||||||
var monitorUrl = '<?php echo $Event->Storage()->Server()->UrlToIndex(); ?>';
|
var monitorUrl = '<?php echo $Event->Storage()->Server()->UrlToIndex(); ?>';
|
||||||
|
|
||||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
||||||
|
@ -63,7 +92,6 @@ var rate = '<?php echo $rate ?>'; // really only used when setting up initial pl
|
||||||
var scale = "<?php echo $scale ?>";
|
var scale = "<?php echo $scale ?>";
|
||||||
var LabelFormat = "<?php echo validJsStr($Monitor->LabelFormat())?>";
|
var LabelFormat = "<?php echo validJsStr($Monitor->LabelFormat())?>";
|
||||||
|
|
||||||
var canEditEvents = <?php echo canEdit('Events')?'true':'false' ?>;
|
|
||||||
var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||||
|
|
||||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||||
|
|
|
@ -58,8 +58,8 @@ function processRows(rows) {
|
||||||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
||||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + row.Name + '</a>'
|
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + row.Name + '</a>'
|
||||||
+ '<br/><div class="small text-nowrap text-muted">' + archived + emailed + '</div>';
|
+ '<br/><div class="small text-nowrap text-muted">' + archived + emailed + '</div>';
|
||||||
if ( canEditMonitors ) row.Monitor = '<a href="?view=monitor&mid=' + mid + '">' + row.Monitor + '</a>';
|
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=monitor&mid=' + mid + '">' + row.Monitor + '</a>';
|
||||||
if ( canEditEvents ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
|
if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
|
||||||
if ( row.Notes.indexOf('detected:') >= 0 ) {
|
if ( row.Notes.indexOf('detected:') >= 0 ) {
|
||||||
row.Cause = row.Cause + '<a href="?view=image&eid=' + eid + '&fid=objdetect"><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></a>';
|
row.Cause = row.Cause + '<a href="?view=image&eid=' + eid + '&fid=objdetect"><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></a>';
|
||||||
} else if ( row.Notes != 'Forced Web: ' ) {
|
} else if ( row.Notes != 'Forced Web: ' ) {
|
||||||
|
@ -74,27 +74,6 @@ function processRows(rows) {
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
function thumbnail_onmouseover(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('stream_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function thumbnail_onmouseout(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('still_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function initThumbAnimation() {
|
|
||||||
if ( WEB_ANIMATE_THUMBS ) {
|
|
||||||
$j('.colThumbnail img').each(function() {
|
|
||||||
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
|
||||||
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the event id's of the selected rows
|
// Returns the event id's of the selected rows
|
||||||
function getIdSelections() {
|
function getIdSelections() {
|
||||||
var table = $j('#eventTable');
|
var table = $j('#eventTable');
|
||||||
|
@ -126,7 +105,7 @@ function getDelConfirmModal() {
|
||||||
// Manage the DELETE CONFIRMATION modal button
|
// Manage the DELETE CONFIRMATION modal button
|
||||||
function manageDelConfirmModalBtns() {
|
function manageDelConfirmModalBtns() {
|
||||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -184,13 +163,13 @@ function initPage() {
|
||||||
function() {
|
function() {
|
||||||
selections = table.bootstrapTable('getSelections');
|
selections = table.bootstrapTable('getSelections');
|
||||||
|
|
||||||
viewBtn.prop('disabled', !(selections.length && canViewEvents));
|
viewBtn.prop('disabled', !(selections.length && canView.Events));
|
||||||
archiveBtn.prop('disabled', !(selections.length && canEditEvents));
|
archiveBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||||
unarchiveBtn.prop('disabled', !(getArchivedSelections()) && canEditEvents);
|
unarchiveBtn.prop('disabled', !(getArchivedSelections()) && canEdit.Events);
|
||||||
editBtn.prop('disabled', !(selections.length && canEditEvents));
|
editBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||||
exportBtn.prop('disabled', !(selections.length && canViewEvents));
|
exportBtn.prop('disabled', !(selections.length && canView.Events));
|
||||||
downloadBtn.prop('disabled', !(selections.length && canViewEvents));
|
downloadBtn.prop('disabled', !(selections.length && canView.Events));
|
||||||
deleteBtn.prop('disabled', !(selections.length && canEditEvents));
|
deleteBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Don't enable the back button if there is no previous zm page to go back to
|
// Don't enable the back button if there is no previous zm page to go back to
|
||||||
|
@ -249,7 +228,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the UNARCHIVE button
|
// Manage the UNARCHIVE button
|
||||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +246,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the EDIT button
|
// Manage the EDIT button
|
||||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +292,7 @@ function initPage() {
|
||||||
|
|
||||||
// Manage the DELETE button
|
// Manage the DELETE button
|
||||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -334,8 +313,7 @@ function initPage() {
|
||||||
var thumb_ndx = $j('#eventTable tr th').filter(function() {
|
var thumb_ndx = $j('#eventTable tr th').filter(function() {
|
||||||
return $j(this).text().trim() == 'Thumbnail';
|
return $j(this).text().trim() == 'Thumbnail';
|
||||||
}).index();
|
}).index();
|
||||||
var thmbClass = WEB_ANIMATE_THUMBS ? 'colThumbnail zoom' : 'colThumbnail';
|
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail');
|
||||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass(thmbClass);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
table.bootstrapTable('resetSearch');
|
table.bootstrapTable('resetSearch');
|
||||||
|
|
|
@ -12,4 +12,3 @@ var emailedString = "<?php echo translate('Emailed') ?>";
|
||||||
var yesString = "<?php echo translate('Yes') ?>";
|
var yesString = "<?php echo translate('Yes') ?>";
|
||||||
var noString = "<?php echo translate('No') ?>";
|
var noString = "<?php echo translate('No') ?>";
|
||||||
var WEB_LIST_THUMBS = <?php echo ZM_WEB_LIST_THUMBS?'true':'false' ?>;
|
var WEB_LIST_THUMBS = <?php echo ZM_WEB_LIST_THUMBS?'true':'false' ?>;
|
||||||
var WEB_ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
|
||||||
|
|
|
@ -31,11 +31,11 @@ function startDownload(file) {
|
||||||
|
|
||||||
function exportProgress() {
|
function exportProgress() {
|
||||||
if ( exportTimer ) {
|
if ( exportTimer ) {
|
||||||
var tickerText = $('exportProgressTicker').get('text');
|
var tickerText = $j('#exportProgressTicker').text();
|
||||||
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
||||||
$('exportProgressTicker').set('text', '.');
|
$j('#exportProgressTicker').text('.');
|
||||||
} else {
|
} else {
|
||||||
$('exportProgressTicker').appendText('.');
|
$j('#exportProgressTicker').append('.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,9 @@ function exportProgress() {
|
||||||
function exportResponse(respObj, respText) {
|
function exportResponse(respObj, respText) {
|
||||||
clearInterval(exportTimer);
|
clearInterval(exportTimer);
|
||||||
if ( respObj.result != 'Ok' ) {
|
if ( respObj.result != 'Ok' ) {
|
||||||
$('exportProgressTicker').set('text', respObj.message);
|
$j('#exportProgressTicker').text(respObj.message);
|
||||||
} else {
|
} else {
|
||||||
$('exportProgressTicker').set('text', exportSucceededString);
|
$j('#exportProgressTicker').text(exportSucceededString);
|
||||||
startDownload.pass(decodeURIComponent(respObj.exportFile)).delay(1500);
|
startDownload.pass(decodeURIComponent(respObj.exportFile)).delay(1500);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -64,12 +64,10 @@ function exportResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportEvents( ) {
|
function exportEvents( ) {
|
||||||
var parms = 'view=event&request=event&action=export';
|
|
||||||
parms += '&'+$('contentForm').toQueryString();
|
|
||||||
var query = new Request.JSON( {
|
var query = new Request.JSON( {
|
||||||
url: thisUrl,
|
url: '?view=event&request=event&action=export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: parms,
|
data: $('contentForm').toQueryString(),
|
||||||
onSuccess: exportResponse
|
onSuccess: exportResponse
|
||||||
} );
|
} );
|
||||||
query.send();
|
query.send();
|
||||||
|
|
|
@ -40,6 +40,24 @@ document.addEventListener('DOMContentLoaded', function onDCL() {
|
||||||
document.getElementById('scaleControl').addEventListener('change', changeScale);
|
document.getElementById('scaleControl').addEventListener('change', changeScale);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getStat(params) {
|
||||||
|
$j.getJSON(thisUrl + '?view=request&request=stats&raw=true', params)
|
||||||
|
.done(function(data) {
|
||||||
|
var stat = data.raw;
|
||||||
|
|
||||||
|
$j('#frameStatsTable').empty().append('<tbody>');
|
||||||
|
$j.each( statHeaderStrings, function( key ) {
|
||||||
|
var th = $j('<th>').addClass('text-right').text(statHeaderStrings[key]);
|
||||||
|
var tdString = ( stat ) ? stat[key] : 'n/a';
|
||||||
|
var td = $j('<td>').text(tdString);
|
||||||
|
var row = $j('<tr>').append(th, td);
|
||||||
|
|
||||||
|
$j('#frameStatsTable tbody').append(row);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.fail(logAjaxFail);
|
||||||
|
}
|
||||||
|
|
||||||
function initPage() {
|
function initPage() {
|
||||||
var backBtn = $j('#backBtn');
|
var backBtn = $j('#backBtn');
|
||||||
|
|
||||||
|
@ -65,6 +83,9 @@ function initPage() {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
window.location.href = thisUrl+'?view=stats&eid='+eid+'&fid='+fid;
|
window.location.href = thisUrl+'?view=stats&eid='+eid+'&fid='+fid;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Load the frame stats
|
||||||
|
getStat({eid: eid, fid: fid});
|
||||||
}
|
}
|
||||||
|
|
||||||
$j(document).ready(function() {
|
$j(document).ready(function() {
|
||||||
|
|
|
@ -13,3 +13,15 @@ var eid = <?php echo $eid ?>;
|
||||||
var fid = <?php echo $fid ?>;
|
var fid = <?php echo $fid ?>;
|
||||||
var record_event_stats = <?php echo ZM_RECORD_EVENT_STATS ?>;
|
var record_event_stats = <?php echo ZM_RECORD_EVENT_STATS ?>;
|
||||||
var alarmFrame = <?php echo $alarmFrame ?>;
|
var alarmFrame = <?php echo $alarmFrame ?>;
|
||||||
|
|
||||||
|
var statHeaderStrings = {};
|
||||||
|
statHeaderStrings.ZoneName = "<?php echo translate('Zone') ?>";
|
||||||
|
statHeaderStrings.PixelDiff = "<?php echo translate('PixelDiff') ?>";
|
||||||
|
statHeaderStrings.AlarmPixels = "<?php echo translate('AlarmPx') ?>";
|
||||||
|
statHeaderStrings.FilterPixels = "<?php echo translate('FilterPx') ?>";
|
||||||
|
statHeaderStrings.BlobPixels = "<?php echo translate('BlobPx') ?>";
|
||||||
|
statHeaderStrings.Blobs = "<?php echo translate('Blobs') ?>";
|
||||||
|
statHeaderStrings.BlobSizes = "<?php echo translate('BlobSizes') ?>";
|
||||||
|
statHeaderStrings.AlarmLimits = "<?php echo translate('AlarmLimits') ?>";
|
||||||
|
statHeaderStrings.Score = "<?php echo translate('Score') ?>";
|
||||||
|
|
||||||
|
|
|
@ -26,27 +26,6 @@ function processRows(rows) {
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
function thumbnail_onmouseover(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('full_img_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function thumbnail_onmouseout(event) {
|
|
||||||
var img = event.target;
|
|
||||||
img.src = '';
|
|
||||||
img.src = img.getAttribute('img_src');
|
|
||||||
}
|
|
||||||
|
|
||||||
function initThumbAnimation() {
|
|
||||||
if ( WEB_ANIMATE_THUMBS ) {
|
|
||||||
$j('.colThumbnail img').each(function() {
|
|
||||||
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
|
||||||
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processClicks(event, field, value, row, $element) {
|
function processClicks(event, field, value, row, $element) {
|
||||||
if ( field == 'Score' ) {
|
if ( field == 'Score' ) {
|
||||||
window.location.assign('?view=stats&eid='+row.EventId+'&fid='+row.FrameId);
|
window.location.assign('?view=stats&eid='+row.EventId+'&fid='+row.FrameId);
|
||||||
|
@ -118,8 +97,7 @@ function initPage() {
|
||||||
var thumb_ndx = $j('#framesTable tr th').filter(function() {
|
var thumb_ndx = $j('#framesTable tr th').filter(function() {
|
||||||
return $j(this).text().trim() == 'Thumbnail';
|
return $j(this).text().trim() == 'Thumbnail';
|
||||||
}).index();
|
}).index();
|
||||||
var thmbClass = WEB_ANIMATE_THUMBS ? 'colThumbnail zoom' : 'colThumbnail';
|
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail');
|
||||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass(thmbClass);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ function deleteGroup( element ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureButtons( element ) {
|
function configureButtons( element ) {
|
||||||
if ( canEditGroups ) {
|
if ( canEdit.Groups ) {
|
||||||
var form = element.form;
|
var form = element.form;
|
||||||
if ( element.checked ) {
|
if ( element.checked ) {
|
||||||
form.deleteBtn.disabled = (element.value == 0);
|
form.deleteBtn.disabled = (element.value == 0);
|
||||||
|
@ -64,7 +64,7 @@ function configModalBtns() {
|
||||||
console.log("No groupForm found");
|
console.log("No groupForm found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !canEditGroups ) {
|
if ( !canEdit.Groups ) {
|
||||||
console.log("Cannot edit groups");
|
console.log("Cannot edit groups");
|
||||||
form.elements['action'].disabled = disabled;
|
form.elements['action'].disabled = disabled;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -146,6 +146,24 @@ function initPage() {
|
||||||
el.oninput = window['update_estimated_ram_use'].bind(el);
|
el.oninput = window['update_estimated_ram_use'].bind(el);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('select[name="newMonitor[Function]"]').forEach(function(el) {
|
||||||
|
el.onchange = function() {
|
||||||
|
$j('#function_help div').hide();
|
||||||
|
$j('#'+this.value+'Help').show();
|
||||||
|
if ( this.value == 'Monitor' || this.value == 'None' ) {
|
||||||
|
$j('#FunctionEnabled').hide();
|
||||||
|
} else {
|
||||||
|
$j('#FunctionEnabled').show();
|
||||||
|
}
|
||||||
|
if ( this.value == 'Record' || this.value == 'Nodect' ) {
|
||||||
|
$j('#FunctionDecodingEnabled').show();
|
||||||
|
} else {
|
||||||
|
$j('#FunctionDecodingEnabled').hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
el.onchange();
|
||||||
|
});
|
||||||
|
|
||||||
$j('.chosen').chosen();
|
$j('.chosen').chosen();
|
||||||
|
|
||||||
// Don't enable the back button if there is no previous zm page to go back to
|
// Don't enable the back button if there is no previous zm page to go back to
|
||||||
|
|
|
@ -62,11 +62,11 @@ function initPage() {
|
||||||
var NewStorageBtn = $j('#NewStorageBtn');
|
var NewStorageBtn = $j('#NewStorageBtn');
|
||||||
var NewServerBtn = $j('#NewServerBtn');
|
var NewServerBtn = $j('#NewServerBtn');
|
||||||
|
|
||||||
if ( canEditSystem ) enableStorageModal();
|
if ( canEdit.System ) enableStorageModal();
|
||||||
if ( canEditSystem ) enableServerModal();
|
if ( canEdit.System ) enableServerModal();
|
||||||
|
|
||||||
NewStorageBtn.prop('disabled', !canEditSystem);
|
NewStorageBtn.prop('disabled', !canEdit.System);
|
||||||
NewServerBtn.prop('disabled', !canEditSystem);
|
NewServerBtn.prop('disabled', !canEdit.System);
|
||||||
}
|
}
|
||||||
|
|
||||||
$j(document).ready(function() {
|
$j(document).ready(function() {
|
||||||
|
|
|
@ -4,4 +4,3 @@ if ( restartWarning ) {
|
||||||
alert( "<?php echo translate('OptionRestartWarning') ?>" );
|
alert( "<?php echo translate('OptionRestartWarning') ?>" );
|
||||||
}
|
}
|
||||||
|
|
||||||
var canEditSystem = <?php echo canEdit('System') ? 'true' : 'false' ?>;
|
|
||||||
|
|
|
@ -30,29 +30,28 @@ function changeDateTime(e) {
|
||||||
window.location = uri;
|
window.location = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function datetime_change(newDate, oldData) {
|
||||||
|
if (newDate !== oldData.lastVal) {
|
||||||
|
changeDateTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function initPage() {
|
function initPage() {
|
||||||
$j('#minTime').datetimepicker({
|
$j('#minTime').datetimepicker({
|
||||||
timeFormat: "HH:mm:ss",
|
timeFormat: "HH:mm:ss",
|
||||||
dateFormat: "yy-mm-dd",
|
dateFormat: "yy-mm-dd",
|
||||||
maxDate: +0,
|
maxDate: +0,
|
||||||
constrainInput: false,
|
constrainInput: false,
|
||||||
onClose: function(newDate, oldData) {
|
onClose: datetime_change
|
||||||
if (newDate !== oldData.lastVal) {
|
|
||||||
changeDateTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$j('#maxTime').datetimepicker({
|
$j('#maxTime').datetimepicker({
|
||||||
timeFormat: "HH:mm:ss",
|
timeFormat: "HH:mm:ss",
|
||||||
dateFormat: "yy-mm-dd",
|
dateFormat: "yy-mm-dd",
|
||||||
minDate: $j('#minTime').val(),
|
minDate: $j('#minTime').val(),
|
||||||
maxDate: +0,
|
maxDate: +0,
|
||||||
constrainInput: false,
|
constrainInput: false,
|
||||||
onClose: function(newDate, oldData) {
|
onClose: datetime_change
|
||||||
if (newDate !== oldData.lastVal) {
|
|
||||||
changeDateTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Kick everything off
|
// Kick everything off
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
var streamCmdTimer = null;
|
||||||
var streamStatus;
|
var streamStatus;
|
||||||
var auth_hash;
|
var auth_hash;
|
||||||
var alarmState = STATE_IDLE;
|
var alarmState = STATE_IDLE;
|
||||||
|
@ -7,23 +8,7 @@ var settingsBtn = $j('#settingsBtn');
|
||||||
var enableAlmBtn = $j('#enableAlmBtn');
|
var enableAlmBtn = $j('#enableAlmBtn');
|
||||||
var forceAlmBtn = $j('#forceAlmBtn');
|
var forceAlmBtn = $j('#forceAlmBtn');
|
||||||
var table = $j('#eventList');
|
var table = $j('#eventList');
|
||||||
|
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||||
if ( monitorType != 'WebSite' ) {
|
|
||||||
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
|
||||||
if ( auth_hash ) {
|
|
||||||
streamCmdParms += '&auth='+auth_hash;
|
|
||||||
}
|
|
||||||
var streamCmdReq = new Request.JSON( {
|
|
||||||
url: monitorUrl,
|
|
||||||
method: 'get',
|
|
||||||
timeout: AJAX_TIMEOUT,
|
|
||||||
link: 'chain',
|
|
||||||
onError: getStreamCmdError,
|
|
||||||
onSuccess: getStreamCmdResponse,
|
|
||||||
onFailure: getStreamCmdFailure
|
|
||||||
} );
|
|
||||||
var streamCmdTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is the format of the json object sent by bootstrap-table
|
This is the format of the json object sent by bootstrap-table
|
||||||
|
@ -52,17 +37,14 @@ var params =
|
||||||
|
|
||||||
// Called by bootstrap-table to retrieve zm event data
|
// Called by bootstrap-table to retrieve zm event data
|
||||||
function ajaxRequest(params) {
|
function ajaxRequest(params) {
|
||||||
// Maintain legacy behavior of sorting by Id column only
|
// Maintain legacy behavior by statically setting these parameters
|
||||||
delete params.data.order;
|
params.data.order = 'desc';
|
||||||
delete params.data.limit;
|
params.data.limit = maxDisplayEvents;
|
||||||
params.data.sort = 'Id desc';
|
params.data.sort = 'Id';
|
||||||
params.data.count = maxDisplayEvents;
|
|
||||||
params.data.id = monitorId;
|
|
||||||
if ( auth_hash ) params.data.auth = auth_hash;
|
|
||||||
|
|
||||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=events', params.data)
|
$j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
|
||||||
.done(function(data) {
|
.done(function(data) {
|
||||||
var rows = processRows(data.events);
|
var rows = processRows(data.rows);
|
||||||
// rearrange the result into what bootstrap-table expects
|
// rearrange the result into what bootstrap-table expects
|
||||||
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows});
|
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows});
|
||||||
})
|
})
|
||||||
|
@ -72,45 +54,45 @@ function ajaxRequest(params) {
|
||||||
function processRows(rows) {
|
function processRows(rows) {
|
||||||
$j.each(rows, function(ndx, row) {
|
$j.each(rows, function(ndx, row) {
|
||||||
var eid = row.Id;
|
var eid = row.Id;
|
||||||
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
|
||||||
|
|
||||||
|
row.Delete = '<i class="fa fa-trash text-danger"></i>';
|
||||||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + '">' + eid + '</a>';
|
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + '">' + eid + '</a>';
|
||||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + '">' + row.Name + '</a>';
|
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + '">' + row.Name + '</a>';
|
||||||
row.Frames = '<a href="?view=frames&eid=' + eid + '">' + row.Frames + '</a>';
|
row.Frames = '<a href="?view=frames&eid=' + eid + '">' + row.Frames + '</a>';
|
||||||
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
||||||
row.MaxScore = '<a href="?view=frame&eid=' + eid + '&fid=0">' + row.MaxScore + '</a>';
|
row.MaxScore = '<a href="?view=frame&eid=' + eid + '&fid=0">' + row.MaxScore + '</a>';
|
||||||
row.Delete = '<i class="fa fa-trash text-danger"></i>';
|
if ( LIST_THUMBS ) row.Thumbnail = '<a href="?view=event&eid=' + eid + filterQuery + '&page=1">' + row.imgHtml + '</a>';
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showEvents() {
|
function showEvents() {
|
||||||
$('ptzControls').addClass('hidden');
|
$j('#ptzControls').addClass('hidden');
|
||||||
$('events').removeClass('hidden');
|
$j('#events').removeClass('hidden');
|
||||||
if ( $('eventsControl') ) {
|
if ( $j('#eventsControl') ) {
|
||||||
$('eventsControl').addClass('hidden');
|
$j('#eventsControl').addClass('hidden');
|
||||||
}
|
}
|
||||||
if ( $('controlControl') ) {
|
if ( $j('#controlControl') ) {
|
||||||
$('controlControl').removeClass('hidden');
|
$j('#controlControl').removeClass('hidden');
|
||||||
}
|
}
|
||||||
showMode = 'events';
|
showMode = 'events';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPtzControls() {
|
function showPtzControls() {
|
||||||
$('events').addClass('hidden');
|
$j('#events').addClass('hidden');
|
||||||
$('ptzControls').removeClass('hidden');
|
$j('#ptzControls').removeClass('hidden');
|
||||||
if ( $('eventsControl') ) {
|
if ( $j('#eventsControl') ) {
|
||||||
$('eventsControl').removeClass('hidden');
|
$j('#eventsControl').removeClass('hidden');
|
||||||
}
|
}
|
||||||
if ( $('controlControl') ) {
|
if ( $j('#controlControl') ) {
|
||||||
$('controlControl').addClass('hidden');
|
$j('#controlControl').addClass('hidden');
|
||||||
}
|
}
|
||||||
showMode = 'control';
|
showMode = 'control';
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeScale() {
|
function changeScale() {
|
||||||
var scale = $('scale').get('value');
|
var scale = $j('#scale').val();
|
||||||
var newWidth;
|
var newWidth;
|
||||||
var newHeight;
|
var newHeight;
|
||||||
if ( scale == '0' || scale == 'auto' ) {
|
if ( scale == '0' || scale == 'auto' ) {
|
||||||
|
@ -126,13 +108,14 @@ function changeScale() {
|
||||||
|
|
||||||
Cookie.write('zmWatchScale'+monitorId, scale, {duration: 10*365, samesite: 'strict'});
|
Cookie.write('zmWatchScale'+monitorId, scale, {duration: 10*365, samesite: 'strict'});
|
||||||
|
|
||||||
/*Stream could be an applet so can't use moo tools*/
|
var streamImg = $j('#liveStream'+monitorId);
|
||||||
var streamImg = $('liveStream'+monitorId);
|
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
streamImg.style.width = newWidth + 'px';
|
var oldSrc = streamImg.attr('src');
|
||||||
streamImg.style.height = newHeight + 'px';
|
var newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale));
|
||||||
|
|
||||||
streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale));
|
streamImg.width( newWidth );
|
||||||
|
streamImg.height( newHeight );
|
||||||
|
streamImg.src = newSrc;
|
||||||
} else {
|
} else {
|
||||||
console.error('No element found for liveStream'+monitorId);
|
console.error('No element found for liveStream'+monitorId);
|
||||||
}
|
}
|
||||||
|
@ -147,11 +130,11 @@ function setAlarmState( currentAlarmState ) {
|
||||||
} else if ( alarmState == STATE_ALERT ) {
|
} else if ( alarmState == STATE_ALERT ) {
|
||||||
stateClass = 'alert';
|
stateClass = 'alert';
|
||||||
}
|
}
|
||||||
$('stateValue').set('text', stateStrings[alarmState]);
|
$j('#stateValue').text(stateStrings[alarmState]);
|
||||||
if ( stateClass ) {
|
if ( stateClass ) {
|
||||||
$('stateValue').setProperty('class', stateClass);
|
$j('#stateValue').addClass(stateClass);
|
||||||
} else {
|
} else {
|
||||||
$('stateValue').removeProperty('class');
|
$j('#stateValue').removeClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT );
|
var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT );
|
||||||
|
@ -161,12 +144,13 @@ function setAlarmState( currentAlarmState ) {
|
||||||
var oldAlarm = ( !isAlarmed && wasAlarmed );
|
var oldAlarm = ( !isAlarmed && wasAlarmed );
|
||||||
|
|
||||||
if ( newAlarm ) {
|
if ( newAlarm ) {
|
||||||
|
table.bootstrapTable('refresh');
|
||||||
if ( SOUND_ON_ALARM ) {
|
if ( SOUND_ON_ALARM ) {
|
||||||
// Enable the alarm sound
|
// Enable the alarm sound
|
||||||
if ( !canPlayPauseAudio ) {
|
if ( !canPlayPauseAudio ) {
|
||||||
$('alarmSound').removeClass('hidden');
|
$j('#alarmSound').removeClass('hidden');
|
||||||
} else {
|
} else {
|
||||||
$('MediaPlayer').Play();
|
$j('#MediaPlayer').trigger('play');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( POPUP_ON_ALARM ) {
|
if ( POPUP_ON_ALARM ) {
|
||||||
|
@ -174,15 +158,15 @@ function setAlarmState( currentAlarmState ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( oldAlarm ) { // done with an event do a refresh
|
if ( oldAlarm ) { // done with an event do a refresh
|
||||||
|
table.bootstrapTable('refresh');
|
||||||
if ( SOUND_ON_ALARM ) {
|
if ( SOUND_ON_ALARM ) {
|
||||||
// Disable alarm sound
|
// Disable alarm sound
|
||||||
if ( !canPlayPauseAudio ) {
|
if ( !canPlayPauseAudio ) {
|
||||||
$('alarmSound').addClass('hidden');
|
$j('#alarmSound').addClass('hidden');
|
||||||
} else {
|
} else {
|
||||||
$('MediaPlayer').Stop();
|
$j('#MediaPlayer').trigger('pause');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table.bootstrapTable('refresh');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastAlarmState = alarmState;
|
lastAlarmState = alarmState;
|
||||||
|
@ -194,10 +178,6 @@ function getStreamCmdError(text, error) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStreamCmdFailure(xhr) {
|
|
||||||
console.log(xhr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStreamCmdResponse(respObj, respText) {
|
function getStreamCmdResponse(respObj, respText) {
|
||||||
watchdogOk('stream');
|
watchdogOk('stream');
|
||||||
if ( streamCmdTimer ) {
|
if ( streamCmdTimer ) {
|
||||||
|
@ -207,35 +187,36 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
// The get status command can get backed up, in which case we won't be able to get the semaphore and will exit.
|
// The get status command can get backed up, in which case we won't be able to get the semaphore and will exit.
|
||||||
if ( respObj.status ) {
|
if ( respObj.status ) {
|
||||||
streamStatus = respObj.status;
|
streamStatus = respObj.status;
|
||||||
$('fpsValue').set('text', streamStatus.fps);
|
$j('#fpsValue').text(streamStatus.fps);
|
||||||
|
|
||||||
setAlarmState(streamStatus.state);
|
setAlarmState(streamStatus.state);
|
||||||
|
|
||||||
$('levelValue').set('text', streamStatus.level);
|
$j('#levelValue').text(streamStatus.level);
|
||||||
|
var newClass = 'ok';
|
||||||
if ( streamStatus.level > 95 ) {
|
if ( streamStatus.level > 95 ) {
|
||||||
$('levelValue').className = 'alarm';
|
newClass = 'alarm';
|
||||||
} else if ( streamStatus.level > 80 ) {
|
} else if ( streamStatus.level > 80 ) {
|
||||||
$('levelValue').className = 'alert';
|
newClass = 'alert';
|
||||||
} else {
|
|
||||||
$('levelValue').className = 'ok';
|
|
||||||
}
|
}
|
||||||
|
$j('#levelValue').removeClass();
|
||||||
|
$j('#levelValue').addClass(newClass);
|
||||||
|
|
||||||
var delayString = secsToTime(streamStatus.delay);
|
var delayString = secsToTime(streamStatus.delay);
|
||||||
|
|
||||||
if ( streamStatus.paused == true ) {
|
if ( streamStatus.paused == true ) {
|
||||||
$('modeValue').set('text', 'Paused');
|
$j('#modeValue').text('Paused');
|
||||||
$('rate').addClass('hidden');
|
$j('#rate').addClass('hidden');
|
||||||
$('delayValue').set('text', delayString);
|
$j('#delayValue').text(delayString);
|
||||||
$('delay').removeClass('hidden');
|
$j('#delay').removeClass('hidden');
|
||||||
$('level').removeClass('hidden');
|
$j('#level').removeClass('hidden');
|
||||||
streamCmdPause(false);
|
streamCmdPause(false);
|
||||||
} else if ( streamStatus.delayed == true ) {
|
} else if ( streamStatus.delayed == true ) {
|
||||||
$('modeValue').set('text', 'Replay');
|
$j('#modeValue').text('Replay');
|
||||||
$('rateValue').set('text', streamStatus.rate);
|
$j('#rateValue').text(streamStatus.rate);
|
||||||
$('rate').removeClass('hidden');
|
$j('#rate').removeClass('hidden');
|
||||||
$('delayValue').set('text', delayString);
|
$j('#delayValue').text(delayString);
|
||||||
$('delay').removeClass('hidden');
|
$j('#delay').removeClass('hidden');
|
||||||
$('level').removeClass('hidden');
|
$j('#level').removeClass('hidden');
|
||||||
if ( streamStatus.rate == 1 ) {
|
if ( streamStatus.rate == 1 ) {
|
||||||
streamCmdPlay(false);
|
streamCmdPlay(false);
|
||||||
} else if ( streamStatus.rate > 0 ) {
|
} else if ( streamStatus.rate > 0 ) {
|
||||||
|
@ -252,21 +233,21 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
} // rate
|
} // rate
|
||||||
} else {
|
} else {
|
||||||
$('modeValue').set( 'text', 'Live' );
|
$j('#modeValue').text( 'Live' );
|
||||||
$('rate').addClass( 'hidden' );
|
$j('#rate').addClass( 'hidden' );
|
||||||
$('delay').addClass( 'hidden' );
|
$j('#delay').addClass( 'hidden' );
|
||||||
$('level').addClass( 'hidden' );
|
$j('#level').addClass( 'hidden' );
|
||||||
streamCmdPlay(false);
|
streamCmdPlay(false);
|
||||||
} // end if paused or delayed
|
} // end if paused or delayed
|
||||||
|
|
||||||
$('zoomValue').set('text', streamStatus.zoom);
|
$j('zoomValue').text(streamStatus.zoom);
|
||||||
if ( streamStatus.zoom == '1.0' ) {
|
if ( streamStatus.zoom == '1.0' ) {
|
||||||
setButtonState('zoomOutBtn', 'unavail');
|
setButtonState('zoomOutBtn', 'unavail');
|
||||||
} else {
|
} else {
|
||||||
setButtonState('zoomOutBtn', 'inactive');
|
setButtonState('zoomOutBtn', 'inactive');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( canEditMonitors ) {
|
if ( canEdit.Monitors ) {
|
||||||
if ( streamStatus.enabled ) {
|
if ( streamStatus.enabled ) {
|
||||||
enableAlmBtn.addClass('disabled');
|
enableAlmBtn.addClass('disabled');
|
||||||
enableAlmBtn.prop('title', disableAlarmsStr);
|
enableAlmBtn.prop('title', disableAlarmsStr);
|
||||||
|
@ -284,19 +265,18 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
forceAlmBtn.prop('disabled', true);
|
forceAlmBtn.prop('disabled', true);
|
||||||
}
|
}
|
||||||
enableAlmBtn.prop('disabled', false);
|
enableAlmBtn.prop('disabled', false);
|
||||||
} // end if canEditMonitors
|
} // end if canEdit.Monitors
|
||||||
|
|
||||||
if ( streamStatus.auth ) {
|
if ( streamStatus.auth ) {
|
||||||
auth_hash = streamStatus.auth;
|
auth_hash = streamStatus.auth;
|
||||||
// Try to reload the image stream.
|
// Try to reload the image stream.
|
||||||
var streamImg = $('liveStream');
|
var streamImg = $j('#liveStream'+monitorId);
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
streamImg.src = streamImg.src.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
var oldSrc = streamImg.attr('src');
|
||||||
|
var newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||||
|
streamImg.src = newSrc;
|
||||||
}
|
}
|
||||||
streamCmdParms = streamCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
|
||||||
statusCmdParms = statusCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
controlParms = controlParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
|
||||||
} // end if have a new auth hash
|
} // end if have a new auth hash
|
||||||
} // end if respObj.status
|
} // end if respObj.status
|
||||||
} else {
|
} else {
|
||||||
|
@ -305,9 +285,12 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
// If it's an auth error, we should reload the whole page.
|
// If it's an auth error, we should reload the whole page.
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
if ( 0 ) {
|
if ( 0 ) {
|
||||||
var streamImg = $('liveStream'+monitorId);
|
var streamImg = $j('#liveStream'+monitorId);
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
streamImg.src = streamImg.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
var oldSrc = streamImg.attr('src');
|
||||||
|
var newSrc = oldSrc.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||||
|
|
||||||
|
streamImg.src = newSrc;
|
||||||
console.log('Changing livestream src to ' + streamImg.src);
|
console.log('Changing livestream src to ' + streamImg.src);
|
||||||
} else {
|
} else {
|
||||||
console.log('Unable to find streamImg liveStream');
|
console.log('Unable to find streamImg liveStream');
|
||||||
|
@ -333,7 +316,10 @@ function streamCmdPause( action ) {
|
||||||
setButtonState('fastRevBtn', 'inactive');
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAUSE);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_PAUSE;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,10 +344,21 @@ function streamCmdPlay( action ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PLAY);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_PLAY;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function streamCmdReq(data) {
|
||||||
|
$j.getJSON(thisUrl + '?view=request&request=stream&connkey='+connKey, data)
|
||||||
|
.done(getStreamCmdResponse)
|
||||||
|
.fail(getStreamCmdError);
|
||||||
|
|
||||||
|
streamCmdTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
function streamCmdStop( action ) {
|
function streamCmdStop( action ) {
|
||||||
setButtonState('pauseBtn', 'inactive');
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState('playBtn', 'unavail');
|
setButtonState('playBtn', 'unavail');
|
||||||
|
@ -373,7 +370,10 @@ function streamCmdStop( action ) {
|
||||||
setButtonState('fastRevBtn', 'unavail');
|
setButtonState('fastRevBtn', 'unavail');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_STOP);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_STOP;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
setButtonState('stopBtn', 'unavail');
|
setButtonState('stopBtn', 'unavail');
|
||||||
setButtonState('playBtn', 'active');
|
setButtonState('playBtn', 'active');
|
||||||
|
@ -390,7 +390,10 @@ function streamCmdFastFwd( action ) {
|
||||||
setButtonState('fastRevBtn', 'inactive');
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTFWD);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_FASTFWD;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +408,10 @@ function streamCmdSlowFwd( action ) {
|
||||||
setButtonState('fastRevBtn', 'inactive');
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWFWD);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_SLOWFWD;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
setButtonState('pauseBtn', 'active');
|
setButtonState('pauseBtn', 'active');
|
||||||
if ( monitorStreamReplayBuffer ) {
|
if ( monitorStreamReplayBuffer ) {
|
||||||
|
@ -424,7 +430,10 @@ function streamCmdSlowRev( action ) {
|
||||||
setButtonState('fastRevBtn', 'inactive');
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWREV);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_SLOWREV;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
setButtonState('pauseBtn', 'active');
|
setButtonState('pauseBtn', 'active');
|
||||||
if ( monitorStreamReplayBuffer ) {
|
if ( monitorStreamReplayBuffer ) {
|
||||||
|
@ -443,43 +452,51 @@ function streamCmdFastRev( action ) {
|
||||||
setButtonState('fastRevBtn', 'inactive');
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTREV);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_FASTREV;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdZoomIn( x, y ) {
|
function streamCmdZoomIn( x, y ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.x = x;
|
||||||
|
data.y = y;
|
||||||
|
data.command = CMD_ZOOMIN;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdZoomOut() {
|
function streamCmdZoomOut() {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMOUT);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_ZOOMOUT;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdScale( scale ) {
|
function streamCmdScale( scale ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_SCALE;
|
||||||
|
data.scale = scale;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdPan( x, y ) {
|
function streamCmdPan( x, y ) {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAN+"&x="+x+"&y="+y);
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.x = x;
|
||||||
|
data.y = y;
|
||||||
|
data.command = CMD_PAN;
|
||||||
|
streamCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdQuery() {
|
function streamCmdQuery() {
|
||||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_QUERY);
|
var data = {};
|
||||||
}
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = CMD_QUERY;
|
||||||
if ( monitorType != 'WebSite' ) {
|
streamCmdReq(data);
|
||||||
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
|
|
||||||
if ( auth_hash ) {
|
|
||||||
statusCmdParms += '&auth='+auth_hash;
|
|
||||||
}
|
|
||||||
var statusCmdReq = new Request.JSON( {
|
|
||||||
url: monitorUrl,
|
|
||||||
method: 'get',
|
|
||||||
timeout: AJAX_TIMEOUT,
|
|
||||||
link: 'cancel',
|
|
||||||
onSuccess: getStatusCmdResponse
|
|
||||||
} );
|
|
||||||
var statusCmdTimer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusCmdResponse(respObj, respText) {
|
function getStatusCmdResponse(respObj, respText) {
|
||||||
|
@ -489,7 +506,7 @@ function getStatusCmdResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( respObj.result == 'Ok' ) {
|
if ( respObj.result == 'Ok' ) {
|
||||||
$('fpsValue').set('text', respObj.monitor.FrameRate);
|
$j('#fpsValue').text(respObj.monitor.FrameRate);
|
||||||
setAlarmState(respObj.monitor.Status);
|
setAlarmState(respObj.monitor.Status);
|
||||||
} else {
|
} else {
|
||||||
checkStreamForErrors('getStatusCmdResponse', respObj);
|
checkStreamForErrors('getStatusCmdResponse', respObj);
|
||||||
|
@ -503,23 +520,23 @@ function getStatusCmdResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function statusCmdQuery() {
|
function statusCmdQuery() {
|
||||||
statusCmdReq.send(statusCmdParms);
|
$j.getJSON(thisUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId)
|
||||||
|
.done(getStatusCmdResponse)
|
||||||
|
.fail(logAjaxFail);
|
||||||
|
|
||||||
|
streamCmdTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
function alarmCmdReq(data) {
|
||||||
var alarmCmdParms = 'view=request&request=alarm&id='+monitorId;
|
$j.getJSON(thisUrl + '?view=request&request=alarm&id='+monitorId, data)
|
||||||
if ( auth_hash ) {
|
.done(getAlarmCmdResponse)
|
||||||
alarmCmdParms += '&auth='+auth_hash;
|
.fail(function(jqxhr, textStatus, error) {
|
||||||
}
|
if (textstatus === "timeout") {
|
||||||
var alarmCmdReq = new Request.JSON( {
|
streamCmdQuery();
|
||||||
url: monitorUrl,
|
} else {
|
||||||
method: 'get',
|
logAjaxFail(jqxhr, textStatus, error);
|
||||||
timeout: AJAX_TIMEOUT,
|
}
|
||||||
link: 'cancel',
|
});
|
||||||
onSuccess: getAlarmCmdResponse,
|
|
||||||
onTimeout: streamCmdQuery
|
|
||||||
} );
|
|
||||||
var alarmCmdFirst = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAlarmCmdResponse(respObj, respText) {
|
function getAlarmCmdResponse(respObj, respText) {
|
||||||
|
@ -527,11 +544,17 @@ function getAlarmCmdResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdDisableAlarms() {
|
function cmdDisableAlarms() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=disableAlarms");
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = 'disableAlarms';
|
||||||
|
alarmCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdEnableAlarms() {
|
function cmdEnableAlarms() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=enableAlarms");
|
var data = {};
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.command = 'enableAlarms';
|
||||||
|
alarmCmdReq(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdAlarm() {
|
function cmdAlarm() {
|
||||||
|
@ -543,17 +566,19 @@ function cmdAlarm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdForceAlarm() {
|
function cmdForceAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
var data = {};
|
||||||
if ( window.event ) {
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
window.event.preventDefault();
|
data.command = 'forceAlarm';
|
||||||
}
|
alarmCmdReq(data);
|
||||||
|
if ( window.event ) window.event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdCancelForcedAlarm() {
|
function cmdCancelForcedAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
var data = {};
|
||||||
if ( window.event ) {
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
window.event.preventDefault();
|
data.command = 'cancelForcedAlarm';
|
||||||
}
|
alarmCmdReq(data);
|
||||||
|
if ( window.event ) window.event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,18 +590,10 @@ function cmdForce() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
function controlReq(data) {
|
||||||
var controlParms = 'view=request&request=control&id='+monitorId;
|
$j.getJSON(thisUrl + '?view=request&request=control&id='+monitorId, data)
|
||||||
if ( auth_hash ) {
|
.done(getControlResponse)
|
||||||
controlParms += '&auth='+auth_hash;
|
.fail(logAjaxFail);
|
||||||
}
|
|
||||||
var controlReq = new Request.JSON( {
|
|
||||||
url: monitorUrl,
|
|
||||||
method: 'post',
|
|
||||||
timeout: AJAX_TIMEOUT,
|
|
||||||
link: 'cancel',
|
|
||||||
onSuccess: getControlResponse
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getControlResponse(respObj, respText) {
|
function getControlResponse(respObj, respText) {
|
||||||
|
@ -595,60 +612,73 @@ function controlCmd(event) {
|
||||||
xtell = button.getAttribute('data-xtell');
|
xtell = button.getAttribute('data-xtell');
|
||||||
ytell = button.getAttribute('data-ytell');
|
ytell = button.getAttribute('data-ytell');
|
||||||
|
|
||||||
var locParms = '';
|
var data = {};
|
||||||
|
|
||||||
if ( event && (xtell || ytell) ) {
|
if ( event && (xtell || ytell) ) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
var coords = $(target).getCoordinates();
|
var offset = $j(target).offset();
|
||||||
|
var width = $j(target).width();
|
||||||
|
var height = $j(target).height();
|
||||||
|
|
||||||
var x = event.pageX - coords.left;
|
var x = event.pageX - offset.left;
|
||||||
var y = event.pageY - coords.top;
|
var y = event.pageY - offset.top;
|
||||||
|
|
||||||
if ( xtell ) {
|
if ( xtell ) {
|
||||||
var xge = parseInt((x*100)/coords.width);
|
var xge = parseInt((x*100)/width);
|
||||||
if ( xtell == -1 ) {
|
if ( xtell == -1 ) {
|
||||||
xge = 100 - xge;
|
xge = 100 - xge;
|
||||||
} else if ( xtell == 2 ) {
|
} else if ( xtell == 2 ) {
|
||||||
xge = 2*(50 - xge);
|
xge = 2*(50 - xge);
|
||||||
}
|
}
|
||||||
locParms += '&xge='+xge;
|
data.xge = xge;
|
||||||
}
|
}
|
||||||
if ( ytell ) {
|
if ( ytell ) {
|
||||||
var yge = parseInt((y*100)/coords.height);
|
var yge = parseInt((y*100)/height);
|
||||||
if ( ytell == -1 ) {
|
if ( ytell == -1 ) {
|
||||||
yge = 100 - yge;
|
yge = 100 - yge;
|
||||||
} else if ( ytell == 2 ) {
|
} else if ( ytell == 2 ) {
|
||||||
yge = 2*(50 - yge);
|
yge = 2*(50 - yge);
|
||||||
}
|
}
|
||||||
locParms += '&yge='+yge;
|
data.yge = yge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controlReq.send(controlParms+"&control="+control+locParms);
|
|
||||||
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
|
data.control = control;
|
||||||
|
controlReq(data);
|
||||||
|
|
||||||
if ( streamMode == 'single' ) {
|
if ( streamMode == 'single' ) {
|
||||||
fetchImage.pass($('imageFeed').getElement('img')).delay(1000);
|
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function controlCmdImage( x, y ) {
|
function controlCmdImage( x, y ) {
|
||||||
var imageControlParms = controlParms;
|
var data = {};
|
||||||
imageControlParms += '&scale='+scale;
|
if ( auth_hash ) data.auth = auth_hash;
|
||||||
imageControlParms += '&control='+imageControlMode;
|
data.scale = scale;
|
||||||
|
data.control = imageControlMode;
|
||||||
|
data.x = x;
|
||||||
|
data.y = y;
|
||||||
|
controlReq(data);
|
||||||
|
|
||||||
controlReq.send( imageControlParms+"&x="+x+"&y="+y );
|
|
||||||
if ( streamMode == 'single' ) {
|
if ( streamMode == 'single' ) {
|
||||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchImage( streamImage ) {
|
function fetchImage( streamImage ) {
|
||||||
streamImage.src = streamImage.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
streamImage.attr('src', streamImage.attr('src').replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick( event ) {
|
function handleClick( event ) {
|
||||||
var $target = $(event.target);
|
var target = event.target;
|
||||||
var scaleX = parseInt(monitorWidth / $target.getWidth());
|
var width = $j(target).width();
|
||||||
var scaleY = parseInt(monitorHeight / $target.getHeight());
|
var height = $j(target).height();
|
||||||
var x = (event.page.x - $target.getLeft()) * scaleX;
|
|
||||||
var y = (event.page.y - $target.getTop()) * scaleY;
|
var scaleX = parseInt(monitorWidth / width);
|
||||||
|
var scaleY = parseInt(monitorHeight / height);
|
||||||
|
var x = (event.page.x - target.getLeft()) * scaleX;
|
||||||
|
var y = (event.page.y - target.getTop()) * scaleY;
|
||||||
|
|
||||||
if ( showMode == 'events' || !imageControlMode ) {
|
if ( showMode == 'events' || !imageControlMode ) {
|
||||||
if ( event.shift ) {
|
if ( event.shift ) {
|
||||||
|
@ -665,11 +695,11 @@ function handleClick( event ) {
|
||||||
|
|
||||||
function appletRefresh() {
|
function appletRefresh() {
|
||||||
if ( streamStatus && (!streamStatus.paused && !streamStatus.delayed) ) {
|
if ( streamStatus && (!streamStatus.paused && !streamStatus.delayed) ) {
|
||||||
var streamImg = $('liveStream'+monitorId);
|
var streamImg = $j('#liveStream'+monitorId);
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
var parent = streamImg.getParent();
|
var parent = streamImg.parent();
|
||||||
streamImg.dispose();
|
streamImg.remove();
|
||||||
streamImg.inject( parent );
|
streamImg.append( parent );
|
||||||
} else {
|
} else {
|
||||||
console.error("Nothing found for liveStream"+monitorId);
|
console.error("Nothing found for liveStream"+monitorId);
|
||||||
}
|
}
|
||||||
|
@ -711,15 +741,9 @@ function reloadWebSite() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePresetLabels() {
|
function updatePresetLabels() {
|
||||||
var form = $('ctrlPresetForm');
|
var lblNdx = $j( '#ctrlPresetForm option:selected' ).val();
|
||||||
var preset_ddm = form.elements['preset'];
|
|
||||||
|
|
||||||
var presetIndex = preset_ddm[preset_ddm.selectedIndex].value;
|
$j('#newLabel').val(labels[lblNdx]);
|
||||||
if ( labels[presetIndex] ) {
|
|
||||||
form.newLabel.value = labels[presetIndex];
|
|
||||||
} else {
|
|
||||||
form.newLabel.value = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCtrlPresetModal() {
|
function getCtrlPresetModal() {
|
||||||
|
@ -767,7 +791,7 @@ function processClicks(event, field, value, row, $element) {
|
||||||
// Manage the DELETE CONFIRMATION modal button
|
// Manage the DELETE CONFIRMATION modal button
|
||||||
function manageDelConfirmModalBtns() {
|
function manageDelConfirmModalBtns() {
|
||||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||||
if ( ! canEditEvents ) {
|
if ( ! canEdit.Events ) {
|
||||||
enoperm();
|
enoperm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -790,7 +814,7 @@ function manageDelConfirmModalBtns() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initPage() {
|
function initPage() {
|
||||||
if ( canViewControl ) {
|
if ( canView.Control ) {
|
||||||
// Load the PTZ Preset modal into the DOM
|
// Load the PTZ Preset modal into the DOM
|
||||||
if ( monitorControllable ) getCtrlPresetModal();
|
if ( monitorControllable ) getCtrlPresetModal();
|
||||||
// Load the settings modal into the DOM
|
// Load the settings modal into the DOM
|
||||||
|
@ -800,25 +824,25 @@ function initPage() {
|
||||||
if ( monitorType != 'WebSite' ) {
|
if ( monitorType != 'WebSite' ) {
|
||||||
if ( streamMode == 'single' ) {
|
if ( streamMode == 'single' ) {
|
||||||
statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
||||||
watchdogCheck.pass('status').periodical(statusRefreshTimeout*2);
|
setInterval(watchdogCheck, statusRefreshTimeout*2, 'status');
|
||||||
} else {
|
} else {
|
||||||
streamCmdTimer = streamCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
streamCmdTimer = streamCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
||||||
watchdogCheck.pass('stream').periodical(statusRefreshTimeout*2);
|
setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( canStreamNative || (streamMode == 'single') ) {
|
if ( canStreamNative || (streamMode == 'single') ) {
|
||||||
var streamImg = $('imageFeed').getElement('img');
|
var streamImg = $j('#imageFeed img');
|
||||||
if ( !streamImg ) {
|
if ( !streamImg ) {
|
||||||
streamImg = $('imageFeed').getElement('object');
|
streamImg = $j('#imageFeed object');
|
||||||
}
|
}
|
||||||
if ( !streamImg ) {
|
if ( !streamImg ) {
|
||||||
console.error('No streamImg found for imageFeed');
|
console.error('No streamImg found for imageFeed');
|
||||||
} else {
|
} else {
|
||||||
if ( streamMode == 'single' ) {
|
if ( streamMode == 'single' ) {
|
||||||
streamImg.addEvent('click', fetchImage.pass(streamImg));
|
streamImg.click(streamImg, fetchImage);
|
||||||
fetchImage.pass(streamImg).periodical(imageRefreshTimeout);
|
setInterval(fetchImage, imageRefreshTimeout, $j('#imageFeed img'));
|
||||||
} else {
|
} else {
|
||||||
streamImg.addEvent('click', function(event) {
|
streamImg.click(function(event) {
|
||||||
handleClick(event);
|
handleClick(event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -861,7 +885,7 @@ function initPage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only enable the settings button for local cameras
|
// Only enable the settings button for local cameras
|
||||||
settingsBtn.prop('disabled', !canViewControl);
|
settingsBtn.prop('disabled', !canView.Control);
|
||||||
if ( monitorType != 'Local' ) settingsBtn.hide();
|
if ( monitorType != 'Local' ) settingsBtn.hide();
|
||||||
|
|
||||||
// Init the bootstrap-table
|
// Init the bootstrap-table
|
||||||
|
@ -874,6 +898,17 @@ function initPage() {
|
||||||
|
|
||||||
// Take appropriate action when the user clicks on a cell
|
// Take appropriate action when the user clicks on a cell
|
||||||
table.on('click-cell.bs.table', processClicks);
|
table.on('click-cell.bs.table', processClicks);
|
||||||
|
|
||||||
|
// Some toolbar events break the thumbnail animation, so re-init eventlistener
|
||||||
|
table.on('all.bs.table', initThumbAnimation);
|
||||||
|
|
||||||
|
// Update table links each time after new data is loaded
|
||||||
|
table.on('post-body.bs.table', function(data) {
|
||||||
|
var thumb_ndx = $j('#eventList tr th').filter(function() {
|
||||||
|
return $j(this).text().trim() == 'Thumbnail';
|
||||||
|
}).index();
|
||||||
|
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail');
|
||||||
|
});
|
||||||
} // initPage
|
} // initPage
|
||||||
|
|
||||||
// Kick everything off
|
// Kick everything off
|
||||||
|
|
|
@ -50,6 +50,7 @@ var SCALE_BASE = <?php echo SCALE_BASE ?>;
|
||||||
|
|
||||||
var SOUND_ON_ALARM = <?php echo ZM_WEB_SOUND_ON_ALARM ?>;
|
var SOUND_ON_ALARM = <?php echo ZM_WEB_SOUND_ON_ALARM ?>;
|
||||||
var POPUP_ON_ALARM = <?php echo ZM_WEB_POPUP_ON_ALARM ?>;
|
var POPUP_ON_ALARM = <?php echo ZM_WEB_POPUP_ON_ALARM ?>;
|
||||||
|
var LIST_THUMBS = <?php echo ZM_WEB_LIST_THUMBS?'true':'false' ?>;
|
||||||
|
|
||||||
var streamMode = "<?php echo $streamMode ?>";
|
var streamMode = "<?php echo $streamMode ?>";
|
||||||
var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"events" ?>";
|
var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"events" ?>";
|
||||||
|
@ -72,9 +73,7 @@ var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||||
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
|
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
|
||||||
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
||||||
|
|
||||||
var canEditMonitors = <?php echo canEdit( 'Monitors' )?'true':'false' ?>;
|
|
||||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||||
var canViewControl = <?php echo canView( 'Control' )?'true':'false' ?>;
|
|
||||||
|
|
||||||
var canPlayPauseAudio = Browser.ie;
|
var canPlayPauseAudio = Browser.ie;
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,6 @@ var streamSrc = "<?php echo preg_replace( '/&/', '&', $streamSrc ) ?>";
|
||||||
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||||
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
||||||
|
|
||||||
var canEditMonitors = <?php echo canEdit( 'Monitors' )?'true':'false' ?>;
|
|
||||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||||
|
|
||||||
var canPlayPauseAudio = Browser.ie;
|
var canPlayPauseAudio = Browser.ie;
|
||||||
|
|
|
@ -27,7 +27,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog'));
|
||||||
?>
|
?>
|
||||||
<body>
|
<body>
|
||||||
<?php echo getNavBarHTML() ?>
|
<?php echo getNavBarHTML() ?>
|
||||||
<div id="page" class="px-3">
|
<div id="page" class="px-3 table-responsive-sm">
|
||||||
|
|
||||||
<div id="logSummary" class="text-center">
|
<div id="logSummary" class="text-center">
|
||||||
<?php echo translate('State') ?>: <span id="logState"></span> -
|
<?php echo translate('State') ?>: <span id="logState"></span> -
|
||||||
|
@ -62,7 +62,6 @@ xhtmlHeaders(__FILE__, translate('SystemLog'));
|
||||||
data-toolbar="#toolbar"
|
data-toolbar="#toolbar"
|
||||||
data-show-fullscreen="true"
|
data-show-fullscreen="true"
|
||||||
data-maintain-meta-data="true"
|
data-maintain-meta-data="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-show-jump-to="true"
|
data-show-jump-to="true"
|
||||||
data-auto-refresh="true"
|
data-auto-refresh="true"
|
||||||
|
|
|
@ -369,8 +369,10 @@ $fastblendopts_alarm = array(
|
||||||
);
|
);
|
||||||
|
|
||||||
$label_size = array(
|
$label_size = array(
|
||||||
1 => translate('Default'),
|
1 => translate('Small'),
|
||||||
2 => translate('Large'),
|
2 => translate('Default'),
|
||||||
|
3 => translate('Large'),
|
||||||
|
4 => translate('Extra Large'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$codecs = array(
|
$codecs = array(
|
||||||
|
@ -468,7 +470,7 @@ if ( canEdit('Monitors') ) {
|
||||||
<div class="tab-content" id="pills-tabContent">
|
<div class="tab-content" id="pills-tabContent">
|
||||||
<?php
|
<?php
|
||||||
foreach ( $tabs as $name=>$value ) {
|
foreach ( $tabs as $name=>$value ) {
|
||||||
echo '<div id="pills-'.$name.'" class="tab-pane fade'.($name==$tab ? ' show active' : '').'" role="tabpanel" area-labelledby="'.$name.'-tab">';
|
echo '<div id="pills-'.$name.'" class="tab-pane fade'.($name==$tab ? ' show active' : '').'" role="tabpanel" aria-labelledby="'.$name.'-tab">';
|
||||||
?>
|
?>
|
||||||
<table class="major">
|
<table class="major">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -500,6 +502,9 @@ switch ( $name ) {
|
||||||
<td class="text-right pr-3"><?php echo translate('SourceType') ?></td>
|
<td class="text-right pr-3"><?php echo translate('SourceType') ?></td>
|
||||||
<td><?php echo htmlSelect('newMonitor[Type]', $sourceTypes, $monitor->Type()); ?></td>
|
<td><?php echo htmlSelect('newMonitor[Type]', $sourceTypes, $monitor->Type()); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<?php
|
||||||
|
if ( $monitor->Type() != 'WebSite' ) {
|
||||||
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right pr-3"><?php echo translate('Function') ?></td>
|
<td class="text-right pr-3"><?php echo translate('Function') ?></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -510,15 +515,37 @@ switch ( $name ) {
|
||||||
}
|
}
|
||||||
echo htmlSelect('newMonitor[Function]', $function_options, $monitor->Function());
|
echo htmlSelect('newMonitor[Function]', $function_options, $monitor->Function());
|
||||||
?>
|
?>
|
||||||
|
<div id="function_help">
|
||||||
|
<?php
|
||||||
|
foreach ( ZM\getMonitorFunctionTypes() as $fn => $translated ) {
|
||||||
|
if ( isset($OLANG['FUNCTION_'.strtoupper($fn)]) ) {
|
||||||
|
echo '<div class="form-text" id="'.$fn.'Help">'.$OLANG['FUNCTION_'.strtoupper($fn)]['Help'].'</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr id="FunctionEnabled">
|
||||||
<td class="text-right pr-3"><?php echo translate('Enabled') ?></td>
|
<td class="text-right pr-3"><?php echo translate('Analysis Enabled') ?></td>
|
||||||
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php echo $monitor->Enabled() ? ' checked="checked"' : '' ?>/></td>
|
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php echo $monitor->Enabled() ? ' checked="checked"' : '' ?>/>
|
||||||
</tr>
|
|
||||||
<?php
|
<?php
|
||||||
if ( $monitor->Type() != 'WebSite' ) {
|
if ( isset($OLANG['FUNCTION_ANALYSIS_ENABLED']) ) {
|
||||||
|
echo '<div class="form-text">'.$OLANG['FUNCTION_ANALYSIS_ENABLED']['Help'].'</div>';
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="FunctionDecodingEnabled">
|
||||||
|
<td class="text-right pr-3"><?php echo translate('Decoding Enabled') ?></td>
|
||||||
|
<td><input type="checkbox" name="newMonitor[DecodingEnabled]" value="1"<?php echo $monitor->DecodingEnabled() ? ' checked="checked"' : '' ?>/>
|
||||||
|
<?php
|
||||||
|
if ( isset($OLANG['FUNCTION_DECODING_ENABLED']) ) {
|
||||||
|
echo '<div class="form-text">'.$OLANG['FUNCTION_DECODING_ENABLED']['Help'].'</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right pr-3"><?php echo translate('LinkedMonitors'); echo makeHelpLink('OPTIONS_LINKED_MONITORS') ?></td>
|
<td class="text-right pr-3"><?php echo translate('LinkedMonitors'); echo makeHelpLink('OPTIONS_LINKED_MONITORS') ?></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -823,11 +850,14 @@ include('_monitor_source_nvsocket.php');
|
||||||
'320x240'=>'320x240',
|
'320x240'=>'320x240',
|
||||||
'320x200'=>'320x200',
|
'320x200'=>'320x200',
|
||||||
'352x240'=>'352x240 CIF',
|
'352x240'=>'352x240 CIF',
|
||||||
|
'352x480'=>'352x480',
|
||||||
'640x480'=>'640x480',
|
'640x480'=>'640x480',
|
||||||
'640x400'=>'640x400',
|
'640x400'=>'640x400',
|
||||||
'704x240'=>'704x240 2CIF',
|
'704x240'=>'704x240 2CIF',
|
||||||
'704x480'=>'704x480 4CIF',
|
'704x480'=>'704x480 4CIF',
|
||||||
'720x480'=>'720x480 D1',
|
'704x576'=>'704x576 D1 PAL',
|
||||||
|
'720x480'=>'720x480 Full D1 NTSC',
|
||||||
|
'720x576'=>'720x576 Full D1 PAL',
|
||||||
'1280x720'=>'1280x720 720p',
|
'1280x720'=>'1280x720 720p',
|
||||||
'1280x800'=>'1280x800',
|
'1280x800'=>'1280x800',
|
||||||
'1280x960'=>'1280x960 960p',
|
'1280x960'=>'1280x960 960p',
|
||||||
|
@ -989,7 +1019,7 @@ include('_monitor_source_nvsocket.php');
|
||||||
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" min="1"/></td>
|
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" min="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right pr-3"><?php echo translate('EstimatedRamUse') ?></td>
|
<td class="text-right pr-3"><?php echo translate('Estimated Ram Use') ?></td>
|
||||||
<td id="estimated_ram_use"><?php echo human_filesize($monitor->ImageBufferCount() * $monitor->Width() * $monitor->Height() * $monitor->Colours(), 0) ?></td>
|
<td id="estimated_ram_use"><?php echo human_filesize($monitor->ImageBufferCount() * $monitor->Width() * $monitor->Height() * $monitor->Colours(), 0) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -38,30 +38,24 @@ if ( isset($_REQUEST['maxTime']) ) {
|
||||||
$maxTime = strftime('%FT%T',time() - 3600);
|
$maxTime = strftime('%FT%T',time() - 3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filter = array(
|
$filter = new ZM\Filter();
|
||||||
'Query' => array(
|
$filter->addTerm(array('attr'=>'StartDateTime', 'op'=>'>=', 'val'=>$minTime, 'obr'=>'1'));
|
||||||
'terms' => array(
|
$filter->addTerm(array('attr'=>'StartDateTime', 'op'=>'<=', 'val'=>$maxTime, 'cnj'=>'and', 'cbr'=>'1'));
|
||||||
array('attr'=>'StartDateTime', 'op'=>'>=', 'val'=>$minTime, 'obr'=>'1'),
|
|
||||||
array('attr'=>'StartDateTime', 'op'=>'<=', 'val'=>$maxTime, 'cnj'=>'and', 'cbr'=>'1'),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if ( count($selected_monitor_ids) ) {
|
if ( count($selected_monitor_ids) ) {
|
||||||
$filter['Query']['terms'][] = (array('attr'=>'MonitorId', 'op'=>'IN', 'val'=>implode(',', $selected_monitor_ids), 'cnj'=>'and'));
|
$filter->addTerm(array('attr'=>'MonitorId', 'op'=>'IN', 'val'=>implode(',', $selected_monitor_ids), 'cnj'=>'and'));
|
||||||
} else if ( ( $group_id != 0 || isset($_SESSION['ServerId']) || isset($_SESSION['StorageId']) || isset($_SESSION['Status']) ) ) {
|
} else if ( ( $group_id != 0 || isset($_SESSION['ServerId']) || isset($_SESSION['StorageId']) || isset($_SESSION['Status']) ) ) {
|
||||||
# this should be redundant
|
# this should be redundant
|
||||||
for ( $i=0; $i < count($displayMonitors); $i++ ) {
|
for ( $i=0; $i < count($displayMonitors); $i++ ) {
|
||||||
if ( $i == 0 ) {
|
if ( $i == 0 ) {
|
||||||
$filter['Query']['terms'][] = array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'and', 'obr'=>'1');
|
$filter->addTerm(array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'and', 'obr'=>'1'));
|
||||||
} else if ( $i == count($displayMonitors)-1 ) {
|
} else if ( $i == count($displayMonitors)-1 ) {
|
||||||
$filter['Query']['terms'][] = array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'or', 'cbr'=>'1');
|
$filter->addTerm(array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'or', 'cbr'=>'1'));
|
||||||
} else {
|
} else {
|
||||||
$filter['Query']['terms'][] = array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'or');
|
$filter->addTerm(array('attr'=>'MonitorId', 'op'=>'=', 'val'=>$displayMonitors[$i]['Id'], 'cnj'=>'or'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parseFilter($filter);
|
$filterQuery = $filter->querystring();
|
||||||
$filterQuery = $filter['query'];
|
|
||||||
ZM\Debug($filterQuery);
|
ZM\Debug($filterQuery);
|
||||||
|
|
||||||
$eventsSql = 'SELECT *,
|
$eventsSql = 'SELECT *,
|
||||||
|
@ -113,17 +107,16 @@ while ( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<body>
|
<body>
|
||||||
|
<?php echo $navbar ?>
|
||||||
<form name="monitorForm" method="get" action="?">
|
<form name="monitorForm" method="get" action="?">
|
||||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||||
<input type="hidden" name="action" value=""/>
|
<input type="hidden" name="action" value=""/>
|
||||||
|
|
||||||
<?php echo $navbar ?>
|
|
||||||
<div class="filterBar">
|
<div class="filterBar">
|
||||||
<?php echo $filterbar ?>
|
<?php echo $filterbar ?>
|
||||||
<div id="DateTimeDiv">
|
<div id="DateTimeDiv">
|
||||||
<label>Event Start Time</label>
|
<label>Event Start Time</label>
|
||||||
<input type="text" name="minTime" id="minTime" value="<?php echo preg_replace('/T/', ' ', $minTime) ?>" oninput="this.form.submit();"/> to
|
<input type="text" name="minTime" id="minTime" value="<?php echo preg_replace('/T/', ' ', $minTime) ?>"/> to
|
||||||
<input type="text" name="maxTime" id="maxTime" value="<?php echo preg_replace('/T/', ' ', $maxTime) ?>" oninput="this.form.submit();"/>
|
<input type="text" name="maxTime" id="maxTime" value="<?php echo preg_replace('/T/', ' ', $maxTime) ?>"/>
|
||||||
</div>
|
</div>
|
||||||
</div><!--FilterBar-->
|
</div><!--FilterBar-->
|
||||||
|
|
||||||
|
@ -150,12 +143,7 @@ for ( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
$Monitor = new ZM\Monitor($monitor);
|
$Monitor = new ZM\Monitor($monitor);
|
||||||
$montagereview_link = '?view=montagereview&live=0&MonitorId='.$monitor['Id'].'&minTime='.$minTime.'&maxTime='.$maxTime;
|
$montagereview_link = '?view=montagereview&live=0&MonitorId='.$monitor['Id'].'&minTime='.$minTime.'&maxTime='.$maxTime;
|
||||||
|
|
||||||
$monitor_filter = addFilterTerm(
|
$monitor_filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'=', 'val'=>$monitor['Id']));
|
||||||
$filter,
|
|
||||||
count($filter['Query']['terms']),
|
|
||||||
array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'=', 'val'=>$monitor['Id'])
|
|
||||||
);
|
|
||||||
parseFilter($monitor_filter);
|
|
||||||
|
|
||||||
if ( isset($EventsByMonitor[$Monitor->Id()]) ) {
|
if ( isset($EventsByMonitor[$Monitor->Id()]) ) {
|
||||||
$EventCounts = $EventsByMonitor[$Monitor->Id()];
|
$EventCounts = $EventsByMonitor[$Monitor->Id()];
|
||||||
|
@ -175,24 +163,12 @@ for ( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( count($FileMissing) ) {
|
if ( count($FileMissing) ) {
|
||||||
$FileMissing_filter = array(
|
$FileMissing_filter = new ZM\Filter();
|
||||||
'Query' => array(
|
$FileMissing_filter->addTerm(array('attr'=>'Id', 'op'=>'IN', 'val'=>implode(',', array_map(function($Event){return $Event->Id();}, $FileMissing))));
|
||||||
'terms' => array(
|
|
||||||
array('attr'=>'Id', 'op'=>'IN', 'val'=>implode(',', array_map(function($Event){return $Event->Id();}, $FileMissing)))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
parseFilter($FileMissing_filter);
|
|
||||||
}
|
}
|
||||||
if ( count($ZeroSize) ) {
|
if ( count($ZeroSize) ) {
|
||||||
$ZeroSize_filter = array(
|
$ZeroSize_filter = new ZM\Filter();
|
||||||
'Query' => array(
|
$ZeroSize_filter->addTerm(array('attr'=>'Id', 'op'=>'IN', 'val'=>implode(',', array_map(function($Event){return $Event->Id();}, $ZeroSize))));
|
||||||
'terms' => array(
|
|
||||||
array('attr'=>'Id', 'op'=>'IN', 'val'=>implode(',', array_map(function($Event){return $Event->Id();}, $ZeroSize)))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
parseFilter($ZeroSize_filter);
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
|
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
|
||||||
|
@ -202,24 +178,27 @@ for ( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
<div class="small text-nowrap text-muted">
|
<div class="small text-nowrap text-muted">
|
||||||
<?php echo implode('<br/>',
|
<?php echo implode('<br/>',
|
||||||
array_map(function($group_id){
|
array_map(function($group_id){
|
||||||
$Group = new ZM\Group($group_id);
|
$Group = ZM\Group::find_one(array('Id'=>$group_id));
|
||||||
$Groups = $Group->Parents();
|
if ( $Group ) {
|
||||||
array_push($Groups, $Group);
|
$Groups = $Group->Parents();
|
||||||
return implode(' > ', array_map(function($Group){ return '<a href="?view=montagereview&GroupId='.$Group->Id().'">'.$Group->Name().'</a>'; }, $Groups ));
|
array_push( $Groups, $Group );
|
||||||
|
}
|
||||||
|
return implode(' > ', array_map(function($Group){ return '<a href="?view=montagereview&GroupId='.$Group->Id().'">'.validHtmlStr($Group->Name()).'</a>'; }, $Groups ));
|
||||||
}, $Monitor->GroupIds()));
|
}, $Monitor->GroupIds()));
|
||||||
|
|
||||||
?>
|
?>
|
||||||
</div></td>
|
</div></td>
|
||||||
<td class="colServer"><?php echo validHtmlStr($Monitor->Server()->Name())?></td>
|
<td class="colServer"><?php echo validHtmlStr($Monitor->Server()->Name())?></td>
|
||||||
<td class="colEvents"><a href="?view=<?php echo ZM_WEB_EVENTS_VIEW ?>&page=1<?php echo $monitor_filter['query'] ?>"><?php echo isset($EventsByMonitor[$Monitor->Id()])?count($EventsByMonitor[$Monitor->Id()]['Events']):0 ?></a></td>
|
<td class="colEvents"><a href="?view=<?php echo ZM_WEB_EVENTS_VIEW ?>&page=1<?php echo $monitor_filter->querystring() ?>"><?php echo isset($EventsByMonitor[$Monitor->Id()])?count($EventsByMonitor[$Monitor->Id()]['Events']):0 ?></a></td>
|
||||||
<td class="colFirstEvent"><?php echo $FirstEvent ? $FirstEvent->link_to($FirstEvent->Id().' at '.$FirstEvent->StartDateTime()) : 'none'?></td>
|
<td class="colFirstEvent"><?php echo $FirstEvent ? $FirstEvent->link_to($FirstEvent->Id().' at '.$FirstEvent->StartDateTime()) : 'none'?></td>
|
||||||
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at '.$LastEvent->StartDateTime()) : 'none'?></td>
|
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at '.$LastEvent->StartDateTime()) : 'none'?></td>
|
||||||
<td class="colMinGap"><?php echo $MinGap ?></td>
|
<td class="colMinGap"><?php echo $MinGap ?></td>
|
||||||
<td class="colMaxGap"><?php echo $MaxGap ?></td>
|
<td class="colMaxGap"><?php echo $MaxGap ?></td>
|
||||||
<td class="colFileMissing<?php echo count($FileMissing) ? ' errorText' : ''?>">
|
<td class="colFileMissing<?php echo count($FileMissing) ? ' errorText' : ''?>">
|
||||||
<?php echo count($FileMissing) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$FileMissing_filter['query'].'">'.count($FileMissing).'</a>' : '0' ?>
|
<?php echo count($FileMissing) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$FileMissing_filter->querystring().'">'.count($FileMissing).'</a>' : '0' ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="colZeroSize<?php echo count($ZeroSize) ? ' errorText' : ''?>">
|
<td class="colZeroSize<?php echo count($ZeroSize) ? ' errorText' : ''?>">
|
||||||
<?php echo count($ZeroSize) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$ZeroSize_filter['query'].'">'.count($ZeroSize).'</a>' : '0' ?>
|
<?php echo count($ZeroSize) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$ZeroSize_filter->querystring().'">'.count($ZeroSize).'</a>' : '0' ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -44,7 +44,9 @@ xhtmlHeaders(__FILE__, translate('Stats')." - ".$eid." - ".$fid );
|
||||||
<div id="content" class="row justify-content-center">
|
<div id="content" class="row justify-content-center">
|
||||||
<form name="contentForm" id="contentForm" method="get" action="?">
|
<form name="contentForm" id="contentForm" method="get" action="?">
|
||||||
<input type="hidden" name="view" value="none"/>
|
<input type="hidden" name="view" value="none"/>
|
||||||
<?php echo getStatsTableHTML($eid, $fid) ?>
|
<div class="table-responsive-sm">
|
||||||
|
<?php echo getStatsTableHTML($eid, $fid) ?>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -145,7 +145,7 @@ $tree = false;
|
||||||
if ( isset($_REQUEST['filter']) ) {
|
if ( isset($_REQUEST['filter']) ) {
|
||||||
$filter = ZM\Filter::parse($_REQUEST['filter']);
|
$filter = ZM\Filter::parse($_REQUEST['filter']);
|
||||||
$tree = $filter->tree();
|
$tree = $filter->tree();
|
||||||
ZM\Warning("Parse tree: " . print_r($tree,true));
|
ZM\Debug('Parse tree: ' . print_r($tree,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isset($_REQUEST['range']) )
|
if ( isset($_REQUEST['range']) )
|
||||||
|
|
|
@ -172,17 +172,14 @@ if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
||||||
data-show-columns="true"
|
data-show-columns="true"
|
||||||
data-show-export="true"
|
data-show-export="true"
|
||||||
data-uncheckAll="true"
|
data-uncheckAll="true"
|
||||||
data-mobile-responsive="true"
|
|
||||||
data-buttons-class="btn btn-normal"
|
data-buttons-class="btn btn-normal"
|
||||||
data-auto-refresh="true"
|
|
||||||
data-auto-refresh-silent="true"
|
|
||||||
data-show-refresh="true"
|
data-show-refresh="true"
|
||||||
data-auto-refresh-interval="5"
|
|
||||||
class="table-sm table-borderless"
|
class="table-sm table-borderless"
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<!-- Row styling is handled by bootstrap-tables -->
|
<!-- Row styling is handled by bootstrap-tables -->
|
||||||
<tr>
|
<tr>
|
||||||
|
<th data-sortable="false" data-field="Delete"><?php echo translate('Delete') ?></th>
|
||||||
<th data-sortable="false" data-field="Id"><?php echo translate('Id') ?></th>
|
<th data-sortable="false" data-field="Id"><?php echo translate('Id') ?></th>
|
||||||
<th data-sortable="false" data-field="Name"><?php echo translate('Name') ?></th>
|
<th data-sortable="false" data-field="Name"><?php echo translate('Name') ?></th>
|
||||||
<th data-sortable="false" data-field="StartDateTime"><?php echo translate('AttrStartTime') ?></th>
|
<th data-sortable="false" data-field="StartDateTime"><?php echo translate('AttrStartTime') ?></th>
|
||||||
|
@ -191,7 +188,7 @@ if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
||||||
<th data-sortable="false" data-field="AlarmFrames"><?php echo translate('AlarmBrFrames') ?></th>
|
<th data-sortable="false" data-field="AlarmFrames"><?php echo translate('AlarmBrFrames') ?></th>
|
||||||
<th data-sortable="false" data-field="AvgScore"><?php echo translate('AvgBrScore') ?></th>
|
<th data-sortable="false" data-field="AvgScore"><?php echo translate('AvgBrScore') ?></th>
|
||||||
<th data-sortable="false" data-field="MaxScore"><?php echo translate('MaxBrScore') ?></th>
|
<th data-sortable="false" data-field="MaxScore"><?php echo translate('MaxBrScore') ?></th>
|
||||||
<th data-sortable="false" data-field="Delete"><?php echo translate('Delete') ?></th>
|
<th data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,8 @@ if ( $errorText ) {
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! ($fh = @fopen($path,'rb') ) ) {
|
if ( ! ($fh = @fopen($path, 'rb') ) ) {
|
||||||
|
ZM\Error('Can\'t open video at '.$path);
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue