Merge branch 'master' into storageareas

This commit is contained in:
Isaac Connor 2017-06-13 18:02:28 -04:00
commit 085d239a6e
38 changed files with 428 additions and 282 deletions

View File

@ -103,6 +103,8 @@ mark_as_advanced(
ZM_PERL_MM_PARMS
ZM_PERL_SEARCH_PATH
ZM_TARGET_DISTRO
ZM_PATH_MAP
ZM_PATH_ARP
ZM_CONFIG_DIR
ZM_CONFIG_SUBDIR
ZM_SYSTEMD)
@ -135,7 +137,21 @@ set(ZM_WEB_USER "" CACHE STRING
set(ZM_WEB_GROUP "" CACHE STRING
"The group apache or the local web server runs on,
Leave empty to be the same as the web user")
set(ZM_DIR_EVENTS "events" CACHE PATH
"Location where events are recorded to, default: events")
set(ZM_DIR_IMAGES "events" CACHE PATH
"Location where images, not directly associated with events,
are recorded to, default: images")
set(ZM_DIR_SOUNDS "sounds" CACHE PATH
"Location to look for optional sound files, default: sounds")
set(ZM_PATH_ZMS "/cgi-bin/nph-zms" CACHE PATH
"Web url to zms streaming server, default: /cgi-bin/nph-zms")
# Advanced
set(ZM_PATH_MAP "/dev/shm" CACHE PATH
"Location to save mapped memory files, default: /dev/shm")
set(ZM_PATH_ARP "" CACHE PATH
"Full path to compatible arp binary. Leave empty for automatic detection.")
set(ZM_CONFIG_DIR "/${CMAKE_INSTALL_SYSCONFDIR}" CACHE PATH
"Location of ZoneMinder configuration, default system config directory")
set(ZM_CONFIG_SUBDIR "${ZM_CONFIG_DIR}/conf.d" CACHE PATH
@ -183,6 +199,9 @@ if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc"))
set(ZM_CONFIG_SUBDIR "/etc/zm/conf.d")
set(ZM_WEBDIR "/usr/share/zoneminder/www")
set(ZM_CGIDIR "/usr/libexec/zoneminder/cgi-bin")
set(ZM_DIR_EVENTS "/var/lib/zoneminder/events")
set(ZM_DIR_IMAGES "/var/lib/zoneminder/images")
set(ZM_PATH_ZMS "/cgi-bin-zm/nph-zms")
elseif(ZM_TARGET_DISTRO STREQUAL "OS13")
set(ZM_RUNDIR "/var/run/zoneminder")
set(ZM_TMPDIR "/var/run/zoneminder")

View File

@ -70,6 +70,7 @@ ADD src /ZoneMinder/src/
ADD umutils /ZoneMinder/umutils/
ADD web /ZoneMinder/web/
ADD cmakecacheimport.sh CMakeLists.txt version zm.conf.in zmconfgen.pl.in zmlinkcontent.sh.in zoneminder-config.cmake /ZoneMinder/
ADD conf.d /ZoneMinder/conf.d
# Change into the ZoneMinder directory
WORKDIR /ZoneMinder

View File

@ -2,23 +2,4 @@
-- This updates a 1.30.1 database to 1.30.2
--
--
-- Update Filters table to have a Concurrent Column
--
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Filters'
AND table_schema = DATABASE()
AND column_name = 'Concurrent'
) > 0,
"SELECT 'Column Concurrent already exists in Filters'",
"ALTER TABLE Filters ADD COLUMN `Concurrent` tinyint(1) unsigned NOT NULL default '0' AFTER Background"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
ALTER TABLE Users MODIFY MonitorIds TEXT NOT NULL;

20
db/zm_update-1.31.1.sql Normal file
View File

@ -0,0 +1,20 @@
--
-- This updates a 1.30.0 database to 1.30.1
--
-- Add StateId Column to Events.
--
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Events'
AND table_schema = DATABASE()
AND column_name = 'StateId'
) > 0,
"SELECT 'Column StateId exists in Events'",
"ALTER TABLE Events ADD `StateId` int(10) unsigned default NULL AFTER `Notes`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

18
db/zm_update-1.31.2.sql Normal file
View File

@ -0,0 +1,18 @@
--
-- Update Filters table to have a Concurrent Column
--
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Filters'
AND table_schema = DATABASE()
AND column_name = 'Concurrent'
) > 0,
"SELECT 'Column Concurrent already exists in Filters'",
"ALTER TABLE Filters ADD COLUMN `Concurrent` tinyint(1) unsigned NOT NULL default '0' AFTER Background"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -23,7 +23,10 @@ override_dh_auto_configure:
-DZM_WEB_USER=www-data \
-DZM_WEB_GROUP=www-data \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_CONFIG_DIR="/etc/zm"
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_auto_install:
dh_auto_install --buildsystem=cmake

View File

@ -1 +1 @@
../redhat/redalert.wav
../redhat/misc/redalert.wav

View File

@ -33,7 +33,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.30.4
Version: 1.31.0
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@ -142,9 +142,7 @@ too much degradation of performance.
%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud
# Change the following default values
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR %{_localstatedir}/spool/zoneminder-upload
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no

View File

@ -25,7 +25,10 @@ override_dh_auto_configure:
-DZM_SOCKDIR="/var/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CONTENTDIR="/var/cache/zoneminder"
-DZM_CONTENTDIR="/var/cache/zoneminder" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
override_dh_clean:
dh_clean $(MANPAGES1)

View File

@ -63,8 +63,10 @@ override_dh_auto_configure:
-DZM_WEB_USER=www-data \
-DZM_WEB_GROUP=www-data \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_CONFIG_DIR="/etc/zm"
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_auto_test:
# do not run tests...

View File

@ -25,7 +25,10 @@ override_dh_auto_configure:
-DZM_SOCKDIR="/var/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CONTENTDIR="/var/cache/zoneminder"
-DZM_CONTENTDIR="/var/cache/zoneminder" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_clean:
dh_clean $(MANPAGES1)

View File

@ -442,23 +442,6 @@ our @options = (
type => $types{string},
category => 'system',
},
{
name => 'ZM_DIR_EVENTS',
default => 'events',
description => 'Directory where events are stored',
help => q`
This is the path to the events directory where all the event
images and other miscellaneous files are stored. CAUTION: The
directory you specify here cannot be outside the web root. This
is a common mistake. Most users should never change this value.
If you intend to record events to a second disk or network
share, then you should mount the drive or share directly to the
ZoneMinder events folder or follow the instructions in the
ZoneMinder Wiki titled Using a dedicated Hard Drive.
`,
type => $types{directory},
category => 'paths',
},
{
name => 'ZM_USE_DEEP_STORAGE',
default => 'yes',
@ -480,68 +463,6 @@ our @options = (
type => $types{boolean},
category => 'hidden',
},
{
name => 'ZM_DIR_IMAGES',
default => 'images',
description => 'Directory where the images that the ZoneMinder client generates are stored',
help => q`
ZoneMinder generates a myriad of images, mostly of which are
associated with events. For those that aren't this is where
they go. CAUTION: The directory you specify here cannot be
outside the web root. This is a common mistake. Most users
should never change this value. If you intend to save images to
a second disk or network share, then you should mount the drive
or share directly to the ZoneMinder images folder or follow the
instructions in the ZoneMinder Wiki titled Using a dedicated
Hard Drive.
`,
type => $types{directory},
category => 'paths',
},
{
name => 'ZM_DIR_SOUNDS',
default => 'sounds',
description => 'Directory to the sounds that the ZoneMinder client can use',
help => q`
ZoneMinder can optionally play a sound file when an alarm is
detected. This indicates where to look for this file. CAUTION:
The directory you specify here cannot be outside the web root.
Most users should never change this value.
`,
type => $types{directory},
category => 'paths',
},
{
name => 'ZM_DIR_EXPORTS',
default => '@ZM_TMPDIR@',
description => 'Directory where exported archives are stored',
help => q`
This is the path to the exports directory where exported
tar.gz and zip archives are stored. By default this points to
ZoneMinder's temp folder, which often sits in ram. Since exported
archives can potentially become large, it is a good idea to move
this folder to some other location on machines with low memory.
`,
type => $types{directory},
category => 'paths',
},
{
name => 'ZM_PATH_ZMS',
default => '/cgi-bin/nph-zms',
description => 'Web path to zms streaming server',
help => q`
The ZoneMinder streaming server is required to send streamed
images to your browser. It will be installed into the cgi-bin
path given at configuration time. This option determines what
the web path to the server is rather than the local path on
your machine. Ordinarily the streaming server runs in
parser-header mode however if you experience problems with
streaming you can change this to non-parsed-header (nph) mode
by changing 'zms' to 'nph-zms'.
`,
type => $types{rel_path},
category => 'paths',
},
{
name => 'ZM_COLOUR_JPEG_FILES',
default => 'no',
@ -1486,83 +1407,6 @@ our @options = (
type => $types{boolean},
category => 'logging',
},
{
name => 'ZM_PATH_MAP',
default => '/dev/shm',
description => 'Path to the mapped memory files that that ZoneMinder can use',
help => q`
ZoneMinder has historically used IPC shared memory for shared
data between processes. This has it's advantages and
limitations. This version of ZoneMinder can use an alternate
method, mapped memory, instead with can be enabled with the
--enable--mmap directive to configure. This requires less
system configuration and is generally more flexible. However it
requires each shared data segment to map onto a filesystem
file. This option indicates where those mapped files go. You
should ensure that this location has sufficient space for these
files and for the best performance it should be a tmpfs file
system or ramdisk otherwise disk access may render this method
slower than the regular shared memory one.
`,
type => $types{abs_path},
category => 'paths',
},
{
name => 'ZM_PATH_SOCKS',
default => '@ZM_SOCKDIR@',
description => 'Path to the various Unix domain socket files that ZoneMinder uses',
help => q`
ZoneMinder generally uses Unix domain sockets where possible.
This reduces the need for port assignments and prevents
external applications from possibly compromising the daemons.
However each Unix socket requires a .sock file to be created.
This option indicates where those socket files go.
`,
type => $types{abs_path},
category => 'paths',
},
{
name => 'ZM_PATH_LOGS',
default => '@ZM_LOGDIR@',
description => 'Path to the various logs that the ZoneMinder daemons generate',
help => q`
There are various daemons that are used by ZoneMinder to
perform various tasks. Most generate helpful log files and this
is where they go. They can be deleted if not required for
debugging.
`,
type => $types{abs_path},
category => 'paths',
},
{
name => 'ZM_PATH_SWAP',
default => '@ZM_TMPDIR@',
description => 'Path to location for temporary swap images used in streaming',
help => q`
Buffered playback requires temporary swap images to be stored
for each instance of the streaming daemons. This option
determines where these images will be stored. The images will
actually be stored in sub directories beneath this location and
will be automatically cleaned up after a period of time.
`,
type => $types{abs_path},
category => 'paths',
},
{
name => 'ZM_PATH_ARP',
default => '',
description => 'Path to a supported ARP tool',
help => q`
The camera probe function uses Address Resolution Protocol in
order to find known devices on the network. Optionally supply
the full path to \"ip neigh\", \"arp -a\", or any other tool on
your system that returns ip/mac address pairs. If this field is
left empty, ZoneMinder will search for the command \"arp\" and
attempt to use that.
`,
type => $types{abs_path},
category => 'paths',
},
{
name => 'ZM_WEB_TITLE_PREFIX',
default => 'ZM',

View File

@ -311,6 +311,7 @@ if ( $migrateEvents ) {
}
if ( $freshen ) {
print( "\nFreshening configuration in database\n" );
migratePaths();
ZoneMinder::Config::loadConfigFromDB();
ZoneMinder::Config::saveConfigToDB();
}
@ -414,6 +415,7 @@ if ( $version ) {
print( "\nUpgrading database to version ".ZM_VERSION."\n" );
# Update config first of all
migratePaths();
ZoneMinder::Config::loadConfigFromDB();
ZoneMinder::Config::saveConfigToDB();
@ -943,5 +945,62 @@ sub patchDB {
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
}
sub migratePaths {
my $customConfigFile = '@ZM_CONFIG_SUBDIR@/zmcustom.conf';
if ( (! -e $customConfigFile ) && ( ZM_VERSION ge '1.31.0' ) && ($Config{ZM_DYN_DB_VERSION} lt '1.31.1') ) {
my %customConfig;
# Check the traditional default values for the variables previsouly found under Options -> Paths
if ( $Config{ZM_DIR_EVENTS} ne 'events' ) {
$customConfig{ZM_DIR_EVENTS} = $Config{ZM_DIR_EVENTS};
}
if ( $Config{ZM_DIR_IMAGES} ne 'images' ) {
$customConfig{ZM_DIR_IMAGES} = $Config{ZM_DIR_IMAGES};
}
if ( $Config{ZM_DIR_SOUNDS} ne 'sounds' ) {
$customConfig{ZM_DIR_SOUNDS} = $Config{ZM_DIR_SOUNDS};
}
if ( $Config{ZM_PATH_ZMS} ne '@ZM_PATH_ZMS@' ) {
$customConfig{ZM_PATH_ZMS} = $Config{ZM_PATH_ZMS};
}
if ( $Config{ZM_PATH_MAP} ne '/dev/shm' ) {
$customConfig{ZM_PATH_MAP} = $Config{ZM_PATH_MAP};
}
if ( $Config{ZM_PATH_SOCKS} ne '@ZM_SOCKDIR@' ) {
$customConfig{ZM_PATH_SOCKS} = $Config{ZM_PATH_SOCKS};
}
if ( $Config{ZM_PATH_LOGS} ne '@ZM_LOGDIR@' ) {
$customConfig{ZM_PATH_LOGS} = $Config{ZM_PATH_LOGS};
}
if ( $Config{ZM_PATH_SWAP} ne '@ZM_TMPDIR@' ) {
$customConfig{ZM_PATH_SWAP} = $Config{ZM_PATH_SWAP};
}
if ( $Config{ZM_PATH_ARP} ne '' ) {
$customConfig{ZM_PATH_ARP} = $Config{ZM_PATH_ARP};
}
# If any variables differ from their expected default value,
# save them to a config file before they get purged from the database
if ( %customConfig ) {
print("\nMigrating custom config values from Options -> Paths\nto $customConfigFile.\n");
print("\nPlease verify these values before starting ZoneMinder.\n\n");
open(my $fh, '>', $customConfigFile) or die "Could open $customConfigFile for writing: $!.";
print $fh "# These values were autogenerated by zmupdate.pl\n";
print $fh "# You may edit these values. ZoneMinder will not overwrite them.\n";
print $fh "#\n\n";
while (my ($key, $value) = each %customConfig) {
print $fh "$key=$value\n";
}
close $fh;
my $gid = getgrnam('@ZM_WEB_GROUP@');
chown -1, $gid, $customConfigFile;
chmod 0640, $customConfigFile;
}
}
}
1;
__END__

View File

@ -1,9 +1,9 @@
snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", config.path_swap, monitor->Id(), connkey );
snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", staticConfig.PATH_SWAP.c_str(), monitor->Id(), connkey );
int len = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id());
int swap_path_length = strlen(config.path_swap) + snprintf(NULL, 0, "/zmswap-m%d", monitor->Id() ) + snprintf(NULL, 0, "/zmswap-q%06d", connkey ) + 1; // +1 for NULL terminator
int swap_path_length = strlen(staticConfig.PATH_SWAP.c_str()) + snprintf(NULL, 0, "/zmswap-m%d", monitor->Id() ) + snprintf(NULL, 0, "/zmswap-q%06d", connkey ) + 1; // +1 for NULL terminator
if ( connkey && playback_buffer > 0 ) {
@ -11,8 +11,8 @@ int len = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id());
Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX );
} else {
swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix );
Debug( 3, "Checking swap image path %s", config.path_swap );
strncpy( swap_path, config.path_swap, swap_path_length );
Debug( 3, "Checking swap image path %s", staticConfig.PATH_SWAP.c_str() );
strncpy( swap_path, staticConfig.PATH_SWAP.c_str(), swap_path_length );
if ( checkSwapPath( swap_path, false ) ) {
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() );
if ( checkSwapPath( swap_path, true ) ) {

View File

@ -30,9 +30,9 @@
#include <set>
#include <vector>
#include <sys/uio.h>
#if defined(BSD)
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif

View File

@ -161,6 +161,26 @@ void process_configfile( char* configFile) {
staticConfig.SERVER_NAME = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 )
staticConfig.SERVER_ID = atoi(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_DIR_EVENTS" ) == 0 )
staticConfig.DIR_EVENTS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_DIR_IMAGES" ) == 0 )
staticConfig.DIR_IMAGES = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_DIR_SOUNDS" ) == 0 )
staticConfig.DIR_SOUNDS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_DIR_EXPORTS" ) == 0 )
staticConfig.DIR_EXPORTS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_ZMS" ) == 0 )
staticConfig.PATH_ZMS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_MAP" ) == 0 )
staticConfig.PATH_MAP = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_SOCKS" ) == 0 )
staticConfig.PATH_SOCKS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_LOGS" ) == 0 )
staticConfig.PATH_LOGS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_SWAP" ) == 0 )
staticConfig.PATH_SWAP = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_ARP" ) == 0 )
staticConfig.PATH_ARP = std::string(val_ptr);
else {
// We ignore this now as there may be more parameters than the
// c/c++ binaries are bothered about

View File

@ -70,6 +70,16 @@ struct StaticConfig
std::string PATH_WEB;
std::string SERVER_NAME;
unsigned int SERVER_ID;
std::string DIR_EVENTS;
std::string DIR_IMAGES;
std::string DIR_SOUNDS;
std::string DIR_EXPORTS;
std::string PATH_ZMS;
std::string PATH_MAP;
std::string PATH_SOCKS;
std::string PATH_LOGS;
std::string PATH_SWAP;
std::string PATH_ARP;
};
extern StaticConfig staticConfig;

View File

@ -158,7 +158,11 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
if ( symlink( time_path, id_file ) < 0 )
Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno));
} else {
<<<<<<< HEAD
snprintf( path, sizeof(path), "%s/%d/%d", storage->Path(), monitor->Id(), id );
=======
snprintf( path, sizeof(path), "%s/%d/%d", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id );
>>>>>>> master
errno = 0;
stat( path, &statbuf );
@ -572,7 +576,7 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
if ( config.record_diag_images ) {
char diag_glob[PATH_MAX] = "";
snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", config.dir_events, monitor->Id() );
snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Id() );
glob_t pglob;
int glob_status = glob( diag_glob, 0, 0, &pglob );
if ( glob_status != 0 ) {
@ -701,6 +705,7 @@ bool EventStream::loadEventData( int event_id ) {
if ( config.use_deep_storage ) {
struct tm *event_time = localtime( &event_data->start_time );
<<<<<<< HEAD
if ( storage_path[0] == '/' )
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
else
@ -710,6 +715,17 @@ bool EventStream::loadEventData( int event_id ) {
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", storage_path, event_data->monitor_id, event_data->event_id );
else
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id );
=======
if ( staticConfig.DIR_EVENTS.c_str()[0] == '/' )
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.DIR_EVENTS.c_str(), event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
else
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str(), event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
} else {
if ( staticConfig.DIR_EVENTS.c_str()[0] == '/' )
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", staticConfig.DIR_EVENTS.c_str(), event_data->monitor_id, event_data->event_id );
else
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str(), event_data->monitor_id, event_data->event_id );
>>>>>>> master
}
event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[3]);
event_data->duration = atof(dbrow[4]);

View File

@ -413,6 +413,26 @@ static void zm_log_fps(double d, const char *postfix) {
Debug(1, "%1.0fk %s", d / 1000, postfix);
}
void zm_dump_codecpar ( const AVCodecParameters *par ) {
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d) codec_tag(%d) width(%d) height(%d)",
par->codec_type,
par->codec_id,
par->codec_tag,
par->width,
par->height
);
}
void zm_dump_codec ( const AVCodecContext *codec ) {
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d) width(%d) height(%d)",
codec->codec_type,
codec->codec_id,
codec->width,
codec->height
);
}
/* "user interface" functions */
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
char buf[256];

View File

@ -323,6 +323,9 @@ static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, in
#endif
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output);
void zm_dump_codec ( const AVCodecContext *codec );
void zm_dump_codecpar ( const AVCodecParameters *par );
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
#define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src )

View File

@ -146,9 +146,10 @@ int FfmpegCamera::Capture( Image &image ) {
int frameComplete = false;
while ( !frameComplete ) {
int ret;
int avResult = av_read_frame( mFormatContext, &packet );
if ( avResult < 0 ) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
if ( avResult < 0 ) {
av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE);
if (
// Check if EOF.
@ -166,9 +167,31 @@ int FfmpegCamera::Capture( Image &image ) {
Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts );
// What about audio stream? Maybe someday we could do sound detection...
if ( packet.stream_index == mVideoStreamId ) {
int ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
if ( ret < 0 )
Fatal( "Unable to decode frame at frame %d", frameCount );
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_send_packet( mVideoCodecContext, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}
frameComplete = 1;
# else
ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}
#endif
Debug( 4, "Decoded video packet at frame %d", frameCount );
@ -304,10 +327,14 @@ int FfmpegCamera::OpenFfmpeg() {
mVideoStreamId = -1;
mAudioStreamId = -1;
for (unsigned int i=0; i < mFormatContext->nb_streams; i++ ) {
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
if ( mFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ) {
#else
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) {
#endif
#endif
if ( mVideoStreamId == -1 ) {
mVideoStreamId = i;
@ -317,10 +344,14 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(2, "Have another video stream." );
}
}
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
if ( mFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ) {
#else
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) {
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO ) {
#endif
#endif
if ( mAudioStreamId == -1 ) {
mAudioStreamId = i;
@ -337,7 +368,12 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 3, "Found video stream at index %d", mVideoStreamId );
Debug ( 3, "Found audio stream at index %d", mAudioStreamId );
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
mVideoCodecContext = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( mVideoCodecContext, mFormatContext->streams[mVideoStreamId]->codecpar );
#else
mVideoCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
#endif
// STolen from ispy
//this fixes issues with rtsp streams!! woot.
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
@ -361,7 +397,12 @@ int FfmpegCamera::OpenFfmpeg() {
}
if ( mAudioStreamId >= 0 ) {
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
mAudioCodecContext = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( mAudioCodecContext, mFormatContext->streams[mAudioStreamId]->codecpar );
#else
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
#endif
if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
} else {
@ -576,12 +617,13 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
//Video recording
if ( recording.tv_sec ) {
// The directory we are recording to is no longer tied to the current event.
// Need to re-init the videostore with the correct directory and start recording again
// for efficiency's sake, we should test for keyframe before we test for directory change...
if ( videoStore && key_frame && (strcmp(oldDirectory, event_file) != 0 ) ) {
// don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...
// if we store our key frame location with the event will that be enough?
uint32_t last_event_id = monitor->GetLastEventId() ;
if ( last_event_id != monitor->GetVideoWriterEventId() ) {
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, monitor->GetVideoWriterEventId() );
if ( videoStore ) {
Info("Re-starting video storage module");
// I don't know if this is important or not... but I figure we might as well write this last packet out to the store before closing it.
@ -596,9 +638,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
delete videoStore;
videoStore = NULL;
monitor->SetVideoWriterEventId( 0 );
} // end if videoStore
} // end if end of recording
if ( ( ! videoStore ) && key_frame && ( packet.stream_index == mVideoStreamId ) ) {
if ( last_event_id and ! videoStore ) {
//Instantiate the video storage module
if (record_audio) {
@ -627,6 +672,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
this->getMonitor());
} // end if record_audio
strcpy(oldDirectory, event_file);
monitor->SetVideoWriterEventId( last_event_id );
// Need to write out all the frames from the last keyframe?
// No... need to write out all frames from when the event began. Due to PreEventFrames, this could be more than since the last keyframe.
@ -664,6 +710,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
Info("Deleting videoStore instance");
delete videoStore;
videoStore = NULL;
monitor->SetVideoWriterEventId( 0 );
}
// Buffer video packets, since we are not recording.
@ -708,7 +755,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
}
Debug(4, "about to decode video" );
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_send_packet( mVideoCodecContext, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
@ -719,7 +766,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
Debug( 1, "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
zm_av_packet_unref( &packet );
continue;
}

View File

@ -70,7 +70,7 @@ Logger::Logger() :
mFileLevel( NOLOG ),
mSyslogLevel( NOLOG ),
mEffectiveLevel( NOLOG ),
//mLogPath( config.path_logs ),
//mLogPath( staticConfig.PATH_LOGS.c_str() ),
//mLogFile( mLogPath+"/"+mId+".log" ),
mDbConnected( false ),
mLogFileFP( NULL ),
@ -577,7 +577,7 @@ void logInit( const char *name, const Logger::Options &options ) {
if ( !Logger::smInstance )
Logger::smInstance = new Logger();
Logger::Options tempOptions = options;
tempOptions.mLogPath = config.path_logs;
tempOptions.mLogPath = staticConfig.PATH_LOGS.c_str();
Logger::smInstance->initialise( name, tempOptions );
}

View File

@ -76,7 +76,7 @@ Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
#if ZM_MEM_MAPPED
map_fd = -1;
snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id );
snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id );
#else // ZM_MEM_MAPPED
shm_id = 0;
#endif // ZM_MEM_MAPPED
@ -484,7 +484,7 @@ Monitor::Monitor(
bool Monitor::connect() {
Debug(3, "Connecting to monitor. Purpose is %d", purpose );
#if ZM_MEM_MAPPED
snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id );
snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id );
map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 );
if ( map_fd < 0 )
Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) );
@ -636,7 +636,7 @@ Monitor::~Monitor() {
if ( purpose == CAPTURE ) {
// How about we store this in the object on instantiation so that we don't have to do this again.
char mmap_path[PATH_MAX] = "";
snprintf( mmap_path, sizeof(mmap_path), "%s/zm.mmap.%d", config.path_map, id );
snprintf( mmap_path, sizeof(mmap_path), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id );
if ( unlink( mmap_path ) < 0 ) {
Warning( "Can't unlink '%s': %s", mmap_path, strerror(errno) );

View File

@ -162,6 +162,7 @@ protected:
//sizeOf(VideoStoreData) expected to be 4104 bytes on 32bit and 64bit
typedef struct {
uint32_t size;
uint32_t current_event;
char event_file[4096];
timeval recording; // used as both bool and a pointer to the timestamp when recording should begin
//uint32_t frameNumber;
@ -431,6 +432,9 @@ public:
int GetOptSaveJPEGs() const { return( savejpegspref ); }
VideoWriter GetOptVideoWriter() const { return( videowriter ); }
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return( &encoderparamsvec ); }
uint32_t GetLastEventId() const { return shared_data->last_event; }
uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; }
void SetVideoWriterEventId( uint32_t p_event_id ) { video_store_data->current_event = p_event_id; }
unsigned int GetPreEventCount() const { return pre_event_count; };
State GetState() const;

View File

@ -26,17 +26,15 @@
#include <stdlib.h>
#include <stdio.h>
Storage::Storage() {
Warning("Instantiating default Storage Object. Should not happen.");
id = 0;
strcpy(name, "Default");
if ( config.dir_events[0] != '/' ) {
if ( staticConfig.DIR_EVENTS[0] != '/' ) {
// not using an absolute path. Make it one by appending ZM_PATH_WEB
snprintf( path, sizeof (path), "%s/%s", staticConfig.PATH_WEB.c_str( ), config.dir_events );
snprintf( path, sizeof (path), "%s/%s", staticConfig.PATH_WEB.c_str( ), staticConfig.DIR_EVENTS.c_str() );
} else {
strncpy(path, config.dir_events, sizeof(path) );
strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path) );
}
}
@ -67,11 +65,11 @@ Storage::Storage( unsigned int p_id ) {
}
}
if ( ! id ) {
if ( config.dir_events[0] != '/' ) {
if ( staticConfig.DIR_EVENTS[0] != '/' ) {
// not using an absolute path. Make it one by appending ZM_PATH_WEB
snprintf( path, sizeof (path), "%s/%s", staticConfig.PATH_WEB.c_str( ), config.dir_events );
snprintf( path, sizeof (path), "%s/%s", staticConfig.PATH_WEB.c_str( ), staticConfig.DIR_EVENTS.c_str() );
} else {
strncpy(path, config.dir_events, sizeof(path) );
strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path) );
}
Debug(1,"No id passed to Storage constructor. Using default path %s instead", path );
strcpy(name, "Default");

View File

@ -291,7 +291,7 @@ void StreamBase::openComms()
if ( connkey > 0 )
{
unsigned int length = snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey);
unsigned int length = snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", staticConfig.PATH_SOCKS.c_str(), connkey);
if ( length >= sizeof(sock_path_lock) ) {
Warning("Socket lock path was truncated.");
length = sizeof(sock_path_lock)-1;
@ -321,7 +321,7 @@ void StreamBase::openComms()
Debug(3, "Have socket %d", sd );
}
length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey );
length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", staticConfig.PATH_SOCKS.c_str(), connkey );
if ( length >= sizeof(loc_sock_path) ) {
Warning("Socket path was truncated.");
length = sizeof(loc_sock_path)-1;
@ -339,7 +339,7 @@ void StreamBase::openComms()
Fatal( "Can't bind: %s", strerror(errno) );
}
snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey );
snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", staticConfig.PATH_SOCKS.c_str(), connkey );
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
rem_addr.sun_family = AF_UNIX;
} // end if connKey > 0

View File

@ -44,6 +44,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
video_input_context = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( video_input_context, video_input_stream->codecpar );
zm_dump_codecpar( video_input_stream->codecpar );
#else
video_input_context = video_input_stream->codec;
#endif
@ -85,6 +86,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
output_format = oc->oformat;
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
// Since we are not re-encoding, all we have to do is copy the parameters
video_output_context = avcodec_alloc_context3( NULL );
@ -94,7 +96,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Error( "Could not initialize context parameteres");
return;
} else {
Debug( 2, "Success getting parameters");
zm_dump_codec( video_output_context );
}
video_output_stream = avformat_new_stream( oc, NULL );
@ -104,6 +106,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Debug(2, "Success creating video out stream" );
}
if ( ! video_output_context->codec_tag ) {
video_output_context->codec_tag = av_codec_get_tag(oc->oformat->codec_tag, video_input_context->codec_id);
Debug(2, "No codec_tag, setting to %d", video_output_context->codec_tag );
}
// Now copy them to the output stream
ret = avcodec_parameters_from_context( video_output_stream->codecpar, video_output_context );
if ( ret < 0 ) {
@ -112,8 +119,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} else {
Debug(2, "Success setting parameters");
}
zm_dump_codecpar( video_output_stream->codecpar );
zm_dump_stream_format( oc, 0, 0, 1 );
#else
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec );
if ( ! video_output_stream ) {
@ -129,6 +136,15 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} else {
Debug(3, "Success copying context" );
}
if ( ! video_output_context->codec_tag ) {
Debug(2, "No codec_tag");
if (! oc->oformat->codec_tag
|| av_codec_get_id (oc->oformat->codec_tag, video_input_context->codec_tag) == video_output_context->codec_id
|| av_codec_get_tag(oc->oformat->codec_tag, video_input_context->codec_id) <= 0) {
Warning("Setting codec tag");
video_output_context->codec_tag = video_input_context->codec_tag;
}
}
#endif
// Just copy them from the input, no reason to choose different
@ -146,17 +162,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_output_context->time_base.den
);
// WHY?
//video_output_context->codec_tag = 0;
if ( ! video_output_context->codec_tag ) {
Debug(2, "No codec_tag");
if (! oc->oformat->codec_tag
|| av_codec_get_id (oc->oformat->codec_tag, video_input_context->codec_tag) == video_output_context->codec_id
|| av_codec_get_tag(oc->oformat->codec_tag, video_input_context->codec_id) <= 0) {
Warning("Setting codec tag");
video_output_context->codec_tag = video_input_context->codec_tag;
}
}
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
video_output_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
@ -218,18 +223,31 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Debug(2, "setting parameters");
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
audio_output_context = avcodec_alloc_context3( NULL );
audio_output_context = avcodec_alloc_context3( audio_output_codec );
// Copy params from inputstream to context
ret = avcodec_parameters_to_context( audio_output_context, audio_input_stream->codecpar );
if (ret < 0) {
Error("Unable to copy audio params to context %s\n", av_make_error_string(ret).c_str());
}
ret = avcodec_parameters_from_context( audio_output_stream->codecpar, audio_output_context );
if (ret < 0) {
Error("Unable to copy audio params to stream %s\n", av_make_error_string(ret).c_str());
}
if ( ! audio_output_context->codec_tag ) {
audio_output_context->codec_tag = av_codec_get_tag(oc->oformat->codec_tag, audio_input_context->codec_id);
Debug(2, "Setting audio codec tag to %d", audio_output_context->codec_tag );
}
#else
audio_output_context = audio_output_stream->codec;
ret = avcodec_copy_context(audio_output_context, audio_input_context);
audio_output_context->codec_tag = 0;
#endif
if (ret < 0) {
Error("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
audio_output_stream = NULL;
} else {
audio_output_context->codec_tag = 0;
if ( audio_output_context->channels > 1 ) {
Warning("Audio isn't mono, changing it.");
audio_output_context->channels = 1;
@ -265,10 +283,10 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
zm_dump_stream_format( oc, 1, 0, 1 );
AVDictionary * opts = NULL;
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
//av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0);
if ((ret = avformat_write_header(oc, NULL)) < 0) {
if ((ret = avformat_write_header( oc, &opts )) < 0) {
//if ((ret = avformat_write_header(oc, &opts)) < 0) {
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
/* Write the stream header, if any. */

View File

@ -112,7 +112,7 @@ void Zone::Setup(
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
if ( ! diag_path[0] ) {
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Name(), id);
}
pg_image->WriteJpeg( diag_path );
}
@ -233,7 +233,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
if ( ! diag_path[0] ) {
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Name(), id, 1 );
}
diff_image->WriteJpeg( diag_path );
}
@ -315,7 +315,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) {
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 2 );
}
diff_image->WriteJpeg( diag_path );
}
@ -525,7 +525,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) {
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 3 );
}
diff_image->WriteJpeg( diag_path );
}
@ -572,7 +572,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) {
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 4 );
}
diff_image->WriteJpeg( diag_path );
}

9
utils/packpack/heartbeat.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# A script to provide background noise so Travis doesn't kill us due to inactivity
# written by Andrew Bauer
while true; do
echo "$(date) - Please don't kill us Mr. Travis, we are still running!"
sleep 30s
done

View File

@ -255,7 +255,11 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
setrpmchangelog
echo "Starting packpack..."
packpack/packpack -f utils/packpack/redhat_package.mk redhat_package
utils/packpack/heartbeat.sh &
mypid=$!
packpack/packpack -f utils/packpack/redhat_package.mk redhat_package > buildlog.txt 2>&1
kill $mypid
tail -n 1000 buildlog.txt
# Steps common to Debian based distros
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
@ -275,7 +279,11 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
setdebchangelog
echo "Starting packpack..."
packpack/packpack
utils/packpack/heartbeat.sh &
mypid=$!
packpack/packpack > buildlog.txt 2>&1
kill $mypid
tail -n 1000 buildlog.txt
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
installtrusty
@ -295,7 +303,11 @@ elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86
setdebchangelog
echo "Starting packpack..."
packpack/packpack
utils/packpack/heartbeat.sh &
mypid=$!
packpack/packpack > buildlog.txt 2>&1
kill $mypid
tail -n 1000 buildlog.txt
# If we are running inside Travis then attempt to install the deb we just built
if [ "${TRAVIS}" == "true" ]; then

View File

@ -1 +1 @@
1.31.0
1.31.2

View File

@ -800,7 +800,6 @@ if ( !empty($action) ) {
switch( $_REQUEST['tab'] ) {
case 'system' :
case 'config' :
case 'paths' :
$restartWarning = true;
break;
case 'web' :

View File

@ -73,8 +73,8 @@ function xhtmlHeaders( $file, $title ) {
<script type="text/javascript" src="tools/mootools/mootools-core.js"></script>
<script type="text/javascript" src="tools/mootools/mootools-more.js"></script>
<script type="text/javascript" src="js/mootools.ext.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-ui-1.11.3.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-ui.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
<script type="text/javascript">
//<![CDATA[
@ -82,7 +82,6 @@ function xhtmlHeaders( $file, $title ) {
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
<?php include("skins/$skin/views/js/state.js.php")?>
//-->
//]]>
</script>

1
web/skins/classic/js/jquery-ui.js vendored Symbolic link
View File

@ -0,0 +1 @@
jquery-ui-1.11.3.js

View File

@ -260,8 +260,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<input type="button" class="btn btn-primary" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
<?php echo makePopupButton( '?view=filter&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
<input class="btn btn-primary" type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
<input class="btn btn-danger" type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/>
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
<input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/>
</td>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ ) {

View File

@ -225,7 +225,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
<?php } ?>
</td>
<?php
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "StateId" ) {
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'StateId' ) {
$states = array();
foreach ( dbFetchAll( 'SELECT Id,Name FROM States ORDER BY lower(Name) ASC' ) as $state_row ) {
$states[$state_row['Id']] = $state_row['Name'];

View File

@ -32,7 +32,6 @@ $tabs['system'] = translate('System');
$tabs['config'] = translate('Config');
$tabs['servers'] = translate('Servers');
$tabs['storage'] = translate('Storage');
$tabs['paths'] = translate('Paths');
$tabs['web'] = translate('Web');
$tabs['images'] = translate('Images');
$tabs['logging'] = translate('Logging');

View File

@ -50,3 +50,43 @@ ZM_DB_USER=@ZM_DB_USER@
# ZoneMinder database password
ZM_DB_PASS=@ZM_DB_PASS@
# Full path to the folder events are recorded to.
# The web account user must have full read/write permission to this folder.
ZM_DIR_EVENTS=@ZM_DIR_EVENTS@
# Full path to the folder images, not directly associated with events,
# are recorded to.
# The web account user must have full read/write permission to this folder.
ZM_DIR_IMAGES=@ZM_DIR_IMAGES@
# Foldername under the webroot where ZoneMinder looks for optional sound files
# to play when an alarm is detected.
ZM_DIR_SOUNDS=@ZM_DIR_SOUNDS@
# Full path to the folder where exported archives are stored
# The web account user must have full read/write permission to this folder.
ZM_DIR_EXPORTS=@ZM_TMPDIR@
# ZoneMinder url path to the zms streaming server
ZM_PATH_ZMS=@ZM_PATH_ZMS@
# Full Path to ZoneMinder's mapped memory files
# The web account user must have full read/write permission to this folder.
ZM_PATH_MAP=@ZM_PATH_MAP@
# Full Path to ZoneMinder's socket folder
# The web account user must have full read/write permission to this folder.
ZM_PATH_SOCKS=@ZM_SOCKDIR@
# Full path to ZoneMinder's log folder
# The web account user must have full read/write permission to this folder.
ZM_PATH_LOGS=@ZM_LOGDIR@
# Full path to ZoneMinder's swap folder
# The web account user must have full read/write permission to this folder.
ZM_PATH_SWAP=@ZM_TMPDIR@
# Full path to optional arp binary
# ZoneMinder will find the arp binary automatically on most systems
ZM_PATH_ARP=@ZM_PATH_ARP@