Merge branch 'storageareas' into zma_to_thread
This commit is contained in:
commit
224ca30c86
|
@ -172,7 +172,7 @@ 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}/zm/conf.d" CACHE PATH
|
||||
set(ZM_CONFIG_SUBDIR "${ZM_CONFIG_DIR}/conf.d" CACHE PATH
|
||||
"Location of ZoneMinder configuration subfolder, default: ZM_CONFIG_DIR/conf.d")
|
||||
set(ZM_EXTRA_LIBS "" CACHE STRING
|
||||
"A list of optional libraries, separated by semicolons, e.g. ssl;theora")
|
||||
|
|
|
@ -58,6 +58,7 @@ RUN apt-get update \
|
|||
php-mysql \
|
||||
vlc-data \
|
||||
yasm \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy local code into our container
|
||||
|
|
|
@ -264,7 +264,8 @@ DROP TABLE IF EXISTS `Groups`;
|
|||
CREATE TABLE `Groups` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`MonitorIds` tinytext NOT NULL,
|
||||
`ParentId` int(10) unsigned,
|
||||
`MonitorIds` text NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
|
@ -286,6 +287,31 @@ CREATE TABLE `Logs` (
|
|||
KEY `TimeKey` (`TimeKey`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
--
|
||||
-- Table structure for table `Manufacturers`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `Manufacturers`;
|
||||
CREATE TABLE `Manufacturers` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY (`Name`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
--
|
||||
-- Table structure for table `Models`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `Models`;
|
||||
CREATE TABLE `Models` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL,
|
||||
`ManufacturerId` int(10),
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY (`ManufacturerId`,`Name`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
--
|
||||
-- Table structure for table `MonitorPresets`
|
||||
--
|
||||
|
@ -294,7 +320,7 @@ DROP TABLE IF EXISTS `MonitorPresets`;
|
|||
CREATE TABLE `MonitorPresets` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket') NOT NULL default 'Local',
|
||||
`Device` tinytext,
|
||||
`Channel` tinytext,
|
||||
`Format` int(10) unsigned default NULL,
|
||||
|
|
|
@ -52,7 +52,7 @@ SET @s = (SELECT IF(
|
|||
AND column_name = 'DefaultVideo'
|
||||
) > 0,
|
||||
"SELECT 'Column DefaultVideo exists in Events'",
|
||||
"ALTER TABLE `Events` ADD `DefaultVideo` VARCHAR( 64 ) NOT NULL AFTER `AlarmFrames`"
|
||||
"ALTER TABLE `Events` ADD `DefaultVideo` VARCHAR( 64 ) NOT NULL default '' AFTER `AlarmFrames`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
--
|
||||
-- This adds Manufacturers and Models
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE table_name = 'Manufacturers'
|
||||
AND table_schema = DATABASE()
|
||||
) > 0,
|
||||
"SELECT 'Manufacturers table exists'",
|
||||
"
|
||||
CREATE TABLE `Manufacturers` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY (`Name`)
|
||||
)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE table_name = 'Models'
|
||||
AND table_schema = DATABASE()
|
||||
) > 0,
|
||||
"SELECT 'Models table exists'",
|
||||
"CREATE TABLE `Models` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL,
|
||||
`ManufacturerId` int(10),
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY (`ManufacturerId`,`Name`)
|
||||
)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
--
|
||||
-- Add StorageId column to Monitors
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = 'Groups'
|
||||
AND table_schema = DATABASE()
|
||||
AND column_name = 'ParentId'
|
||||
) > 0,
|
||||
"SELECT 'Column GroupId exists in Groups'",
|
||||
"ALTER TABLE Groups ADD `ParentId` int(10) unsigned AFTER `Name`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE Monitors MODIFY `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket') NOT NULL default 'Local';
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE Groups MODIFY `MonitorIds` text NOT NULL;
|
|
@ -166,7 +166,7 @@ too much degradation of performance.
|
|||
find %{buildroot} \( -name .htaccess -or -name .editorconfig -or -name .packlist -or -name .git -or -name .gitignore -or -name .gitattributes -or -name .travis.yml \) -type f -delete > /dev/null 2>&1 || :
|
||||
|
||||
# Recursively change shebang in all relevant scripts and set execute permission
|
||||
find %{buildroot}%{_datadir}/zoneminder/www/api \( -name cake -or -name cake.php \) -type f -exec sed -i 's\^#!/usr/bin/env bash$\#!/usr/bin/bash\' {} \; -exec %{__chmod} 755 {} \;
|
||||
find %{buildroot}%{_datadir}/zoneminder/www/api \( -name cake -or -name cake.php \) -type f -exec sed -i 's\^#!/usr/bin/env bash$\#!%{_buildshell}\' {} \; -exec %{__chmod} 755 {} \;
|
||||
|
||||
# Use the system cacert file rather then the one bundled with CakePHP
|
||||
%{__rm} -f %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
zoneminder (1.31.4-vivid1) vivid; urgency=medium
|
||||
|
||||
* Release 1.31.4
|
||||
|
||||
-- Isaac Connor <iconnor@tesla.com> Thu, 21 Sep 2017 09:55:31 -0700
|
||||
|
||||
|
|
@ -8,29 +8,4 @@ if [ -h "${ol}" ]; then
|
|||
[ "$(readlink ${ol})" = "/etc/zm/apache.conf" ] && rm -f "${ol}"
|
||||
fi
|
||||
|
||||
abort=false
|
||||
if [ -h /usr/share/zoneminder/www/events ]; then
|
||||
l=$(readlink /usr/share/zoneminder/www/events)
|
||||
if [ "$l" != "/var/cache/zoneminder/events" -a "$l" != "/var/cache/zoneminder/events/" ]; then
|
||||
abort=true
|
||||
fi
|
||||
fi
|
||||
if [ -h /usr/share/zoneminder/www/images ]; then
|
||||
l=$(readlink /usr/share/zoneminder/www/images )
|
||||
if [ "$l" != "/var/cache/zoneminder/images" -a "$l" != "/var/cache/zoneminder/images/" ]; then
|
||||
abort=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$abort" = "true" ]; then
|
||||
cat >&2 << EOF
|
||||
Aborting installation of zoneminder due to non-default symlinks in
|
||||
/usr/share/zoneminder for the images and/or events directory, which could
|
||||
result in loss of data. Please move your data in each of these directories to
|
||||
/var/cache/zoneminder before installing zoneminder from the package.
|
||||
EOF
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
|
|
@ -899,6 +899,21 @@ our @options = (
|
|||
type => $types{integer},
|
||||
category => 'network',
|
||||
},
|
||||
{
|
||||
name => 'ZM_MIN_STREAMING_PORT',
|
||||
default => '',
|
||||
description => 'Alternate port range to contact for streaming video.',
|
||||
help => q`
|
||||
Due to browsers only wanting to open 6 connections, if you have more
|
||||
than 6 monitors, you can have trouble viewing more than 6. This setting
|
||||
specified the beginning of a port range that will be used to contact ZM
|
||||
on. Each monitor will use this value plus the Monitor Id to stream
|
||||
content. So a value of 2000 here will cause a stream for Monitor 1 to
|
||||
hit port 2001. Please ensure that you configure apache appropriately
|
||||
to respond on these ports.`,
|
||||
type => $types{integer},
|
||||
category => 'network',
|
||||
},
|
||||
{
|
||||
name => 'ZM_MIN_RTP_PORT',
|
||||
default => '40200',
|
||||
|
|
|
@ -348,7 +348,12 @@ Debug("Checking for files for event $_[0]{Id} at $path using glob $path/* found
|
|||
|
||||
sub age {
|
||||
if ( ! $_[0]{age} ) {
|
||||
$_[0]{age} = (time() - ($^T - ((-M $_[0]->Path() ) * 24*60*60)));
|
||||
if ( -e $_[0]->Path() ) {
|
||||
# $^T is the time the program began running. -M is program start time - file modification time in days
|
||||
$_[0]{age} = (time() - ($^T - ((-M $_[0]->Path() ) * 24*60*60)));
|
||||
} else {
|
||||
Warning($_[0]->Path() . ' does not appear to exist.');
|
||||
}
|
||||
}
|
||||
return $_[0]{age};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
|
||||
|
||||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||
set(ZM_BIN_SRC_FILES zm_analysis_thread.cpp 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_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_ffmpeg_input.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_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)
|
||||
set(ZM_BIN_SRC_FILES zm_analysis_thread.cpp 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_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_ffmpeg_input.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)
|
||||
|
||||
# A fix for cmake recompiling the source files for every target.
|
||||
add_library(zm STATIC ${ZM_BIN_SRC_FILES})
|
||||
|
|
|
@ -124,7 +124,7 @@ MYSQL_RES *zmDbRow::fetch( const char *query ) {
|
|||
result_set = NULL;
|
||||
Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) );
|
||||
} else {
|
||||
Debug(3, "Succes");
|
||||
Debug(5, "Success");
|
||||
}
|
||||
return result_set;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
|
|||
// Create event id symlink
|
||||
snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id );
|
||||
if ( symlink( time_path, id_file ) < 0 )
|
||||
Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno));
|
||||
Error( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno));
|
||||
} else {
|
||||
snprintf( path, sizeof(path), "%s/%d/%d", storage->Path(), monitor->Id(), id );
|
||||
|
||||
|
@ -156,14 +156,14 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
|
|||
Error( "Can't mkdir %s: %s", path, strerror(errno));
|
||||
}
|
||||
}
|
||||
} // deep storage or not
|
||||
|
||||
// Create empty id tag file
|
||||
snprintf( id_file, sizeof(id_file), "%s/.%d", path, id );
|
||||
if ( FILE *id_fp = fopen( id_file, "w" ) )
|
||||
fclose( id_fp );
|
||||
else
|
||||
Fatal( "Can't fopen %s: %s", id_file, strerror(errno));
|
||||
// Create empty id tag file
|
||||
snprintf( id_file, sizeof(id_file), "%s/.%d", path, id );
|
||||
if ( FILE *id_fp = fopen( id_file, "w" ) )
|
||||
fclose( id_fp );
|
||||
else
|
||||
Error( "Can't fopen %s: %s", id_file, strerror(errno));
|
||||
} // deep storage or not
|
||||
|
||||
last_db_frame = 0;
|
||||
|
||||
|
@ -262,22 +262,22 @@ void Event::createNotes( std::string ¬es ) {
|
|||
int Event::sd = -1;
|
||||
|
||||
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) {
|
||||
Image* ImgToWrite;
|
||||
Image* ts_image = NULL;
|
||||
|
||||
if ( !config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped.
|
||||
{
|
||||
ts_image = new Image(*image);
|
||||
monitor->TimestampImage( ts_image, ×tamp );
|
||||
ImgToWrite=ts_image;
|
||||
} else
|
||||
ImgToWrite=image;
|
||||
|
||||
int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default
|
||||
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||
bool rc;
|
||||
Debug(3, "Writing image to %s", event_file );
|
||||
|
||||
if(ts_image) delete(ts_image); // clean up if used.
|
||||
return( true );
|
||||
if ( !config.timestamp_on_capture ) {
|
||||
// stash the image we plan to use in another pointer regardless if timestamped.
|
||||
Image *ts_image = new Image(*image);
|
||||
monitor->TimestampImage( ts_image, ×tamp );
|
||||
rc = ts_image->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||
delete(ts_image);
|
||||
} else {
|
||||
rc = image->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow ) {
|
||||
|
@ -483,20 +483,23 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
|
|||
static char event_file[PATH_MAX];
|
||||
snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );
|
||||
|
||||
if ( monitor->GetOptSaveJPEGs() & 4) {
|
||||
if ( monitor->GetOptSaveJPEGs() & 4 ) {
|
||||
//If this is the first frame, we should add a thumbnail to the event directory
|
||||
if(frames == 10){
|
||||
if ( frames == 10 ) {
|
||||
char snapshot_file[PATH_MAX];
|
||||
snprintf( snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path );
|
||||
WriteFrameImage( image, timestamp, snapshot_file );
|
||||
}
|
||||
}
|
||||
if( monitor->GetOptSaveJPEGs() & 1) {
|
||||
Debug( 1, "Writing capture frame %d", frames );
|
||||
WriteFrameImage( image, timestamp, event_file );
|
||||
if ( monitor->GetOptSaveJPEGs() & 1 ) {
|
||||
Debug( 1, "Writing capture frame %d to %s", frames, event_file );
|
||||
if ( ! WriteFrameImage( image, timestamp, event_file ) ) {
|
||||
Error("Failed to write frame image");
|
||||
}
|
||||
}
|
||||
if ( videowriter != NULL ) {
|
||||
WriteFrameVideo( image, timestamp, videowriter );
|
||||
Debug(3, "Writing video");
|
||||
WriteFrameVideo(image, timestamp, videowriter);
|
||||
}
|
||||
|
||||
struct DeltaTimeval delta_time;
|
||||
|
@ -535,7 +538,7 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
|
|||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if db_frame
|
||||
|
||||
end_time = timestamp;
|
||||
|
||||
|
@ -551,8 +554,8 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
|
|||
snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames );
|
||||
|
||||
Debug( 1, "Writing analysis frame %d", frames );
|
||||
if ( monitor->GetOptSaveJPEGs() & 2) {
|
||||
WriteFrameImage( alarm_image, timestamp, event_file, true );
|
||||
if ( monitor->GetOptSaveJPEGs() & 2 ) {
|
||||
WriteFrameImage(alarm_image, timestamp, event_file, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -832,38 +832,44 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
startTime,
|
||||
this->getMonitor());
|
||||
} // end if record_audio
|
||||
strcpy(oldDirectory, event_file);
|
||||
monitor->SetVideoWriterEventId( last_event_id );
|
||||
if ( ! videoStore->open() ) {
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
|
||||
// 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.
|
||||
unsigned int packet_count = 0;
|
||||
ZMPacket *queued_packet;
|
||||
} else {
|
||||
strcpy(oldDirectory, event_file);
|
||||
monitor->SetVideoWriterEventId( last_event_id );
|
||||
|
||||
// Clear all packets that predate the moment when the recording began
|
||||
packetqueue.clear_unwanted_packets( &recording, mVideoStreamId );
|
||||
// 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.
|
||||
unsigned int packet_count = 0;
|
||||
ZMPacket *queued_packet;
|
||||
|
||||
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
||||
AVPacket *avp = queued_packet->av_packet();
|
||||
// Clear all packets that predate the moment when the recording began
|
||||
packetqueue.clear_unwanted_packets( &recording, mVideoStreamId );
|
||||
|
||||
packet_count += 1;
|
||||
//Write the packet to our video store
|
||||
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", avp->stream_index, avp->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
|
||||
if ( avp->stream_index == mVideoStreamId ) {
|
||||
ret = videoStore->writeVideoFramePacket( avp );
|
||||
have_video_keyframe = true;
|
||||
} else if ( avp->stream_index == mAudioStreamId ) {
|
||||
ret = videoStore->writeAudioFramePacket( avp );
|
||||
} else {
|
||||
Warning("Unknown stream id in queued packet (%d)", avp->stream_index );
|
||||
ret = -1;
|
||||
}
|
||||
if ( ret < 0 ) {
|
||||
//Less than zero and we skipped a frame
|
||||
}
|
||||
delete queued_packet;
|
||||
} // end while packets in the packetqueue
|
||||
Debug(2, "Wrote %d queued packets", packet_count );
|
||||
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
||||
AVPacket *avp = queued_packet->av_packet();
|
||||
|
||||
packet_count += 1;
|
||||
//Write the packet to our video store
|
||||
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", avp->stream_index, avp->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
|
||||
if ( avp->stream_index == mVideoStreamId ) {
|
||||
ret = videoStore->writeVideoFramePacket( avp );
|
||||
have_video_keyframe = true;
|
||||
} else if ( avp->stream_index == mAudioStreamId ) {
|
||||
ret = videoStore->writeAudioFramePacket( avp );
|
||||
} else {
|
||||
Warning("Unknown stream id in queued packet (%d)", avp->stream_index );
|
||||
ret = -1;
|
||||
}
|
||||
if ( ret < 0 ) {
|
||||
//Less than zero and we skipped a frame
|
||||
}
|
||||
delete queued_packet;
|
||||
} // end while packets in the packetqueue
|
||||
Debug(2, "Wrote %d queued packets", packet_count );
|
||||
}
|
||||
} // end if ! was recording
|
||||
|
||||
} else {
|
||||
|
|
|
@ -940,33 +940,27 @@ cinfo->out_color_space = JCS_RGB;
|
|||
// Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults.
|
||||
// Note quality=zero means default
|
||||
|
||||
bool Image::WriteJpeg( const char *filename, int quality_override) const
|
||||
{
|
||||
bool Image::WriteJpeg(const char *filename, int quality_override) const {
|
||||
return Image::WriteJpeg(filename, quality_override, (timeval){0,0});
|
||||
}
|
||||
bool Image::WriteJpeg( const char *filename) const
|
||||
{
|
||||
bool Image::WriteJpeg(const char *filename) const {
|
||||
return Image::WriteJpeg(filename, 0, (timeval){0,0});
|
||||
}
|
||||
bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const
|
||||
{
|
||||
return Image::WriteJpeg(filename,0,timestamp);
|
||||
bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
|
||||
return Image::WriteJpeg(filename, 0, timestamp);
|
||||
}
|
||||
|
||||
bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const
|
||||
{
|
||||
if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 )
|
||||
{
|
||||
bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const {
|
||||
if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) {
|
||||
Image temp_image( *this );
|
||||
temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB );
|
||||
return( temp_image.WriteJpeg( filename, quality_override, timestamp) );
|
||||
return temp_image.WriteJpeg(filename, quality_override, timestamp);
|
||||
}
|
||||
int quality = quality_override?quality_override:config.jpeg_file_quality;
|
||||
|
||||
struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality];
|
||||
|
||||
if ( !cinfo )
|
||||
{
|
||||
if ( !cinfo ) {
|
||||
cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct;
|
||||
cinfo->err = jpeg_std_error( &jpg_err.pub );
|
||||
jpg_err.pub.error_exit = zm_jpeg_error_exit;
|
||||
|
@ -975,8 +969,7 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
|||
}
|
||||
|
||||
FILE *outfile;
|
||||
if ( (outfile = fopen( filename, "wb" )) == NULL )
|
||||
{
|
||||
if ( (outfile = fopen( filename, "wb" )) == NULL ) {
|
||||
Error( "Can't open %s: %s", filename, strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
|
@ -996,11 +989,11 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
|||
{
|
||||
#ifdef JCS_EXTENSIONS
|
||||
cinfo->input_components = 4;
|
||||
if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) {
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
cinfo->in_color_space = JCS_EXT_BGRX;
|
||||
} else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) {
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
||||
cinfo->in_color_space = JCS_EXT_XRGB;
|
||||
} else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) {
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
||||
cinfo->in_color_space = JCS_EXT_XBGR;
|
||||
} else {
|
||||
/* Assume RGBA */
|
||||
|
@ -1010,7 +1003,7 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
|||
Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source");
|
||||
jpeg_abort_compress( cinfo );
|
||||
fclose(outfile);
|
||||
return(false);
|
||||
return false;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -1018,14 +1011,14 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
|||
default:
|
||||
{
|
||||
cinfo->input_components = 3;
|
||||
if(subpixelorder == ZM_SUBPIX_ORDER_BGR) {
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_BGR) {
|
||||
#ifdef JCS_EXTENSIONS
|
||||
cinfo->in_color_space = JCS_EXT_BGR;
|
||||
#else
|
||||
Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source");
|
||||
jpeg_abort_compress( cinfo );
|
||||
fclose(outfile);
|
||||
return(false);
|
||||
return false;
|
||||
#endif
|
||||
} else {
|
||||
/* Assume RGB */
|
||||
|
@ -1052,8 +1045,7 @@ cinfo->out_color_space = JCS_RGB;
|
|||
}
|
||||
// If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal
|
||||
// No timestamp just leave off the exif section.
|
||||
if(timestamp.tv_sec)
|
||||
{
|
||||
if ( timestamp.tv_sec ) {
|
||||
#define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds
|
||||
#define EXIFTIMES_MS_LEN 0x03
|
||||
#define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes
|
||||
|
@ -1078,17 +1070,16 @@ cinfo->out_color_space = JCS_RGB;
|
|||
|
||||
JSAMPROW row_pointer; /* pointer to a single row */
|
||||
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
|
||||
while ( cinfo->next_scanline < cinfo->image_height )
|
||||
{
|
||||
while ( cinfo->next_scanline < cinfo->image_height ) {
|
||||
row_pointer = &buffer[cinfo->next_scanline * row_stride];
|
||||
jpeg_write_scanlines( cinfo, &row_pointer, 1 );
|
||||
}
|
||||
|
||||
jpeg_finish_compress( cinfo );
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
fclose( outfile );
|
||||
fclose(outfile);
|
||||
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder)
|
||||
|
|
|
@ -112,8 +112,8 @@ Logger::Logger() :
|
|||
|
||||
Logger::~Logger() {
|
||||
terminate();
|
||||
smCodes.clear();
|
||||
smSyslogPriorities.clear();
|
||||
smCodes.clear();
|
||||
smSyslogPriorities.clear();
|
||||
#if 0
|
||||
for ( StringMap::iterator itr = smCodes.begin(); itr != smCodes.end(); itr ++ ) {
|
||||
smCodes.erase( itr );
|
||||
|
@ -193,6 +193,13 @@ void Logger::initialise( const std::string &id, const Options &options ) {
|
|||
}
|
||||
}
|
||||
} // end foreach target
|
||||
} else {
|
||||
// if we don't have debug turned on, then the max effective log level is INFO
|
||||
if ( tempSyslogLevel > INFO ) tempSyslogLevel = INFO;
|
||||
if ( tempFileLevel > INFO ) tempFileLevel = INFO;
|
||||
if ( tempTermLevel > INFO ) tempTermLevel = INFO;
|
||||
if ( tempDatabaseLevel > INFO ) tempDatabaseLevel = INFO;
|
||||
if ( tempLevel > INFO ) tempLevel = INFO;
|
||||
} // end if config.log_debug
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#endif // ZM_HAS_V4L
|
||||
#include "zm_remote_camera.h"
|
||||
#include "zm_remote_camera_http.h"
|
||||
#include "zm_remote_camera_nvsocket.h"
|
||||
#if HAVE_LIBAVFORMAT
|
||||
#include "zm_remote_camera_rtsp.h"
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
|
@ -2526,13 +2527,13 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
|
|||
unsigned int id = atoi(dbrow[col]); col++;
|
||||
std::string name = dbrow[col]; col++;
|
||||
unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
unsigned int storage_id = atoi(dbrow[col]); col++;
|
||||
unsigned int storage_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
std::string type = dbrow[col]; col++;
|
||||
int function = atoi(dbrow[col]); col++;
|
||||
int enabled = atoi(dbrow[col]); col++;
|
||||
std::string linked_monitors = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
|
||||
std::string device = dbrow[col]; col++;
|
||||
std::string device = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
int channel = atoi(dbrow[col]); col++;
|
||||
int format = atoi(dbrow[col]); col++;
|
||||
|
||||
|
@ -2642,6 +2643,22 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
|
|||
#else // ZM_HAS_V4L
|
||||
Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id );
|
||||
#endif // ZM_HAS_V4L
|
||||
} else if ( type == "NVSocket" ) {
|
||||
camera = new RemoteCameraNVSocket(
|
||||
id,
|
||||
host.c_str(),
|
||||
port.c_str(),
|
||||
path.c_str(),
|
||||
width,
|
||||
height,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
} else if ( type == "Remote" ) {
|
||||
if ( protocol == "http" ) {
|
||||
camera = new RemoteCameraHttp(
|
||||
|
|
|
@ -94,3 +94,21 @@ void RemoteCamera::Initialise() {
|
|||
Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) );
|
||||
}
|
||||
}
|
||||
|
||||
int RemoteCamera::Read( int fd, char *buf, int size ) {
|
||||
int ReceivedBytes = 0;
|
||||
int bytes;
|
||||
while ( ReceivedBytes < size ) {
|
||||
// recv blocks until we get data, but it may be of ARBITRARY LENGTH and INCOMPLETE
|
||||
int bytes_to_recv = size - ReceivedBytes;
|
||||
if ( SOCKET_BUF_SIZE < bytes_to_recv )
|
||||
bytes_to_recv = SOCKET_BUF_SIZE;
|
||||
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
|
||||
if ( bytes <= 0 ) {
|
||||
Error("RemoteCamera::Read Recv error. Closing Socket\n");
|
||||
return -1;
|
||||
}
|
||||
ReceivedBytes += bytes;
|
||||
}
|
||||
return ReceivedBytes;
|
||||
}
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define SOCKET_BUF_SIZE 8192
|
||||
|
||||
//
|
||||
// Class representing 'remote' cameras, i.e. those which are
|
||||
// accessed over a network connection.
|
||||
//
|
||||
class RemoteCamera : public Camera
|
||||
{
|
||||
class RemoteCamera : public Camera {
|
||||
protected:
|
||||
std::string protocol;
|
||||
std::string host;
|
||||
|
@ -90,6 +91,7 @@ public:
|
|||
virtual int Capture( Image &image ) = 0;
|
||||
virtual int PostCapture() = 0;
|
||||
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;
|
||||
int Read( int fd, char*buf, int size );
|
||||
};
|
||||
|
||||
#endif // ZM_REMOTE_CAMERA_H
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
//
|
||||
// ZoneMinder Remote Camera Class Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
#include "zm_remote_camera_nvsocket.h"
|
||||
|
||||
#include "zm_mem_utils.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#ifdef SOLARIS
|
||||
#include <sys/filio.h> // FIONREAD and friends
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
RemoteCameraNVSocket::RemoteCameraNVSocket(
|
||||
unsigned int p_monitor_id,
|
||||
const std::string &p_host,
|
||||
const std::string &p_port,
|
||||
const std::string &p_path,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio ) :
|
||||
RemoteCamera(
|
||||
p_monitor_id,
|
||||
"http",
|
||||
p_host,
|
||||
p_port,
|
||||
p_path,
|
||||
p_width,
|
||||
p_height,
|
||||
p_colours,
|
||||
p_brightness,
|
||||
p_contrast,
|
||||
p_hue,
|
||||
p_colour,
|
||||
p_capture,
|
||||
p_record_audio )
|
||||
{
|
||||
sd = -1;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
if ( capture ) {
|
||||
Initialise();
|
||||
}
|
||||
}
|
||||
|
||||
RemoteCameraNVSocket::~RemoteCameraNVSocket() {
|
||||
if ( capture ) {
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteCameraNVSocket::Initialise() {
|
||||
RemoteCamera::Initialise();
|
||||
|
||||
if ( !timeout.tv_sec ) {
|
||||
timeout.tv_sec = config.http_timeout/1000;
|
||||
timeout.tv_usec = (config.http_timeout%1000)*1000;
|
||||
}
|
||||
|
||||
int max_size = width*height*colours;
|
||||
|
||||
buffer.size( max_size );
|
||||
|
||||
mode = SINGLE_IMAGE;
|
||||
format = UNDEF;
|
||||
state = HEADER;
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::Connect() {
|
||||
//struct addrinfo *p;
|
||||
struct sockaddr_in servaddr;
|
||||
bzero( &servaddr, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||
servaddr.sin_port = htons(atoi(port.c_str()));
|
||||
|
||||
|
||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//for(p = hp; p != NULL; p = p->ai_next) {
|
||||
//sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
|
||||
if ( sd < 0 ) {
|
||||
Warning("Can't create socket: %s", strerror(errno) );
|
||||
//continue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) {
|
||||
if ( connect( sd, (struct sockaddr *)&servaddr , sizeof(servaddr) ) < 0 ) {
|
||||
close(sd);
|
||||
sd = -1;
|
||||
|
||||
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
|
||||
return -1;
|
||||
//continue;
|
||||
//}
|
||||
/* If we got here, we must have connected successfully */
|
||||
//break;
|
||||
}
|
||||
|
||||
//if ( p == NULL ) {
|
||||
//Error("Unable to connect to the remote camera, aborting");
|
||||
//return( -1 );
|
||||
//}
|
||||
|
||||
Debug( 3, "Connected to host, socket = %d", sd );
|
||||
return( sd );
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::Disconnect() {
|
||||
close( sd );
|
||||
sd = -1;
|
||||
Debug( 3, "Disconnected from host" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::SendRequest( std::string request ) {
|
||||
Debug( 2, "Sending request: %s", request.c_str() );
|
||||
if ( write( sd, request.data(), request.length() ) < 0 ) {
|
||||
Error( "Can't write: %s", strerror(errno) );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
}
|
||||
Debug( 3, "Request sent" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Return codes are as follows:
|
||||
* -1 means there was an error
|
||||
* 0 means no bytes were returned but there wasn't actually an error.
|
||||
* > 0 is the # of bytes read.
|
||||
*/
|
||||
|
||||
int RemoteCameraNVSocket::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(sd, &rfds);
|
||||
|
||||
struct timeval temp_timeout = timeout;
|
||||
|
||||
int n_found = select(sd+1, &rfds, NULL, NULL, &temp_timeout);
|
||||
if ( n_found == 0 ) {
|
||||
Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec );
|
||||
int error = 0;
|
||||
socklen_t len = sizeof(error);
|
||||
int retval = getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &len);
|
||||
if ( retval != 0 ) {
|
||||
Debug(1, "error getting socket error code %s", strerror(retval));
|
||||
}
|
||||
if ( error != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
// Why are we disconnecting? It's just a timeout, meaning that data wasn't available.
|
||||
//Disconnect();
|
||||
return 0;
|
||||
} else if ( n_found < 0 ) {
|
||||
Error("Select error: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int total_bytes_to_read = 0;
|
||||
|
||||
if ( bytes_expected ) {
|
||||
total_bytes_to_read = bytes_expected;
|
||||
} else {
|
||||
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
|
||||
Error( "Can't ioctl(): %s", strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( total_bytes_to_read == 0 ) {
|
||||
if ( mode == SINGLE_IMAGE ) {
|
||||
int error = 0;
|
||||
socklen_t len = sizeof (error);
|
||||
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
|
||||
if(retval != 0 ) {
|
||||
Debug( 1, "error getting socket error code %s", strerror(retval) );
|
||||
}
|
||||
if (error != 0) {
|
||||
return -1;
|
||||
}
|
||||
// Case where we are grabbing a single jpg, but no content-length was given, so the expectation is that we read until close.
|
||||
return( 0 );
|
||||
}
|
||||
// If socket is closed locally, then select will fail, but if it is closed remotely
|
||||
// then we have an exception on our socket.. but no data.
|
||||
Debug( 3, "Socket closed remotely" );
|
||||
//Disconnect(); // Disconnect is done outside of ReadData now.
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
// There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
|
||||
if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) {
|
||||
total_bytes_to_read = ZM_NETWORK_BUFSIZ;
|
||||
Debug(3, "Just getting 32K" );
|
||||
} else {
|
||||
Debug(3, "Just getting %d", total_bytes_to_read );
|
||||
}
|
||||
} // end if bytes_expected or not
|
||||
Debug( 3, "Expecting %d bytes", total_bytes_to_read );
|
||||
|
||||
int total_bytes_read = 0;
|
||||
do {
|
||||
int bytes_read = buffer.read_into( sd, total_bytes_to_read );
|
||||
if ( bytes_read < 0 ) {
|
||||
Error( "Read error: %s", strerror(errno) );
|
||||
return( -1 );
|
||||
} else if ( bytes_read == 0 ) {
|
||||
Debug( 2, "Socket closed" );
|
||||
//Disconnect(); // Disconnect is done outside of ReadData now.
|
||||
return( -1 );
|
||||
} else if ( (unsigned int)bytes_read < total_bytes_to_read ) {
|
||||
Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read );
|
||||
return( -1 );
|
||||
}
|
||||
Debug( 3, "Read %d bytes", bytes_read );
|
||||
total_bytes_read += bytes_read;
|
||||
total_bytes_to_read -= bytes_read;
|
||||
} while ( total_bytes_to_read );
|
||||
|
||||
Debug( 4, buffer );
|
||||
|
||||
return( total_bytes_read );
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::PreCapture() {
|
||||
if ( sd < 0 ) {
|
||||
Connect();
|
||||
if ( sd < 0 ) {
|
||||
Error( "Unable to connect to camera" );
|
||||
return( -1 );
|
||||
}
|
||||
mode = SINGLE_IMAGE;
|
||||
buffer.clear();
|
||||
}
|
||||
struct image_def {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t type;
|
||||
};
|
||||
struct image_def image_def;
|
||||
|
||||
if ( SendRequest("GetImageParams") < 0 ) {
|
||||
Error( "Unable to send request" );
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
if ( Read(sd, (char *) &image_def, sizeof(image_def)) != sizeof(image_def) ) {
|
||||
Error("Unable to GetImageParams");
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
if ( image_def.width != width || image_def.height != height ) {
|
||||
Error("Incorrect width and height set. %dx%d != %dx%d", width, height, image_def.width, image_def.height );
|
||||
Disconnect();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::Capture( Image &image ) {
|
||||
if ( SendRequest("GetNextImage") < 0 ) {
|
||||
Warning( "Unable to capture image, retrying" );
|
||||
return( 1 );
|
||||
}
|
||||
if ( Read( sd, buffer, imagesize ) < imagesize ) {
|
||||
Warning( "Unable to capture image, retrying" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraNVSocket::PostCapture()
|
||||
{
|
||||
return( 0 );
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// ZoneMinder Remote NVSOCKET Camera Class Interface, $Date$, $Revision$
|
||||
// Copyright (C) 2017 ZoneMinder LLC
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
#ifndef ZM_REMOTE_CAMERA_NVSOCKET_H
|
||||
#define ZM_REMOTE_CAMERA_NVSOCKET_H
|
||||
|
||||
#include "zm_remote_camera.h"
|
||||
|
||||
#include "zm_buffer.h"
|
||||
#include "zm_regexp.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
//
|
||||
// Class representing 'http' cameras, i.e. those which are
|
||||
// accessed over a network connection using http
|
||||
//
|
||||
class RemoteCameraNVSocket : public RemoteCamera {
|
||||
protected:
|
||||
std::string request;
|
||||
struct timeval timeout;
|
||||
//struct hostent *hp;
|
||||
//struct sockaddr_in sa;
|
||||
int sd;
|
||||
Buffer buffer;
|
||||
enum { SINGLE_IMAGE, MULTI_IMAGE } mode;
|
||||
enum { UNDEF, JPEG, X_RGB, X_RGBZ } format;
|
||||
enum { HEADER, HEADERCONT, SUBHEADER, SUBHEADERCONT, CONTENT } state;
|
||||
enum { SIMPLE, REGEXP } method;
|
||||
|
||||
public:
|
||||
RemoteCameraNVSocket(
|
||||
unsigned int p_monitor_id,
|
||||
const std::string &host,
|
||||
const std::string &port,
|
||||
const std::string &path,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio );
|
||||
~RemoteCameraNVSocket();
|
||||
|
||||
void Initialise();
|
||||
void Terminate() { Disconnect(); }
|
||||
int Connect();
|
||||
int Disconnect();
|
||||
int SendRequest( std::string );
|
||||
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
||||
int GetResponse();
|
||||
int PreCapture();
|
||||
int Capture( Image &image );
|
||||
int PostCapture();
|
||||
int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);};
|
||||
};
|
||||
|
||||
#endif // ZM_REMOTE_CAMERA_NVSOCKET_H
|
|
@ -125,7 +125,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
|
||||
#else
|
||||
video_out_stream =
|
||||
avformat_new_stream(oc, reinterpret_cast<const AVCodec *>(video_in_ctx->codec));
|
||||
avformat_new_stream(oc,(const AVCodec *)(video_in_ctx->codec));
|
||||
if (!video_out_stream) {
|
||||
Fatal("Unable to create video out stream\n");
|
||||
} else {
|
||||
|
@ -222,7 +222,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
Debug(3, "Got AAC");
|
||||
|
||||
audio_out_stream =
|
||||
avformat_new_stream(oc, reinterpret_cast<const AVCodec *>(audio_in_ctx->codec));
|
||||
avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec));
|
||||
if (!audio_out_stream) {
|
||||
Error("Unable to create audio out stream\n");
|
||||
audio_out_stream = NULL;
|
||||
|
@ -279,12 +279,25 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
}
|
||||
} // end if audio_in_stream
|
||||
|
||||
|
||||
video_last_pts = 0;
|
||||
video_last_dts = 0;
|
||||
audio_last_pts = 0;
|
||||
audio_last_dts = 0;
|
||||
video_next_pts = 0;
|
||||
video_next_dts = 0;
|
||||
audio_next_pts = 0;
|
||||
audio_next_dts = 0;
|
||||
} // VideoStore::VideoStore
|
||||
|
||||
bool VideoStore::open() {
|
||||
/* open the out file, if needed */
|
||||
if (!(out_format->flags & AVFMT_NOFILE)) {
|
||||
ret = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
Fatal("Could not open out file '%s': %s\n", filename,
|
||||
Error("Could not open out file '%s': %s\n", filename,
|
||||
av_make_error_string(ret).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,18 +323,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
if (ret < 0) {
|
||||
Error("Error occurred when writing out file header to %s: %s\n",
|
||||
filename, av_make_error_string(ret).c_str());
|
||||
return false;
|
||||
}
|
||||
if (opts) av_dict_free(&opts);
|
||||
|
||||
video_last_pts = 0;
|
||||
video_last_dts = 0;
|
||||
audio_last_pts = 0;
|
||||
audio_last_dts = 0;
|
||||
video_next_pts = 0;
|
||||
video_next_dts = 0;
|
||||
audio_next_pts = 0;
|
||||
audio_next_dts = 0;
|
||||
} // VideoStore::VideoStore
|
||||
return true;
|
||||
}
|
||||
|
||||
VideoStore::~VideoStore() {
|
||||
if (audio_out_codec) {
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
AVStream *audio_in_stream,
|
||||
int64_t nStartTime,
|
||||
Monitor * p_monitor);
|
||||
bool open();
|
||||
~VideoStore();
|
||||
|
||||
int writeVideoFramePacket( AVPacket *pkt );
|
||||
|
|
|
@ -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", staticConfig.DIR_EVENTS.c_str(), monitor->Name(), id);
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-poly.jpg", monitor->getStorage()->Path(), 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", staticConfig.DIR_EVENTS.c_str(), monitor->Name(), id, 1 );
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), 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", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 2 );
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), 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", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 3 );
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), 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", staticConfig.DIR_EVENTS.c_str(), monitor->Id(), id, 4 );
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), id, 4 );
|
||||
}
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
|
@ -981,5 +981,5 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
|
|||
/* Store the results */
|
||||
*pixel_count = pixelsalarmed;
|
||||
*pixel_sum = pixelsdifference;
|
||||
Debug( 7, "STORED");
|
||||
Debug(7, "STORED pixelsalarmed(%d), pixelsdifference(%d)", pixelsalarmed, pixelsdifference);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
|
||||
use Getopt::Long ();
|
||||
|
||||
my $opts = {};
|
||||
Getopt::Long::GetOptions($opts, 'help', 'output=s',
|
||||
'pid_file=s', 'db_port=s', 'db_name=s', 'db_host=s', 'db_user=s', 'db_pass=s',
|
||||
'min_port=s','max_port=s', 'debug=s',
|
||||
'server_name=s','error_log=s','protocol=s',
|
||||
);
|
||||
|
||||
if ($opts->{help}) {
|
||||
usage();
|
||||
exit 0;
|
||||
} # end if
|
||||
|
||||
|
||||
my %defaults = (
|
||||
error_log => '/var/log/apache2/error.log',
|
||||
output => '/etc/apache2/sites-available/zoneminder.conf',
|
||||
protocol => 'http',
|
||||
);
|
||||
|
||||
foreach my $key ( keys %defaults ) {
|
||||
if ( ! $$opts{$key} ) {
|
||||
$$opts{$key} = $defaults{$key};
|
||||
}
|
||||
}
|
||||
|
||||
my $Listen = '';
|
||||
my $VirtualHostPorts;
|
||||
|
||||
if ( $$opts{protocol} eq 'https' ) {
|
||||
if ( ! $$opts{server_name} ) {
|
||||
die "https requires a server_name";
|
||||
}
|
||||
$VirtualHostPorts = ' *:443';
|
||||
}
|
||||
|
||||
|
||||
foreach my $port ( $$opts{min_port} .. $$opts{max_port} ) {
|
||||
$Listen .= "Listen $port $$opts{protocol}\n";
|
||||
$VirtualHostPorts .= " *:$port";
|
||||
}
|
||||
|
||||
my $template =qq`
|
||||
$Listen
|
||||
<VirtualHost$VirtualHostPorts>
|
||||
DocumentRoot /usr/share/zoneminder/www
|
||||
`. ( $$opts{server_name} ? ' ServerName ' . $$opts{server_name} : '' ).
|
||||
qq`
|
||||
ErrorLog $$opts{error_log}
|
||||
|
||||
ScriptAlias /zm/cgi-bin/ /usr/lib/zoneminder/cgi-bin/
|
||||
ScriptAlias /cgi-bin/ /usr/lib/zoneminder/cgi-bin/
|
||||
<Directory "/usr/lib/zoneminder/cgi-bin">
|
||||
AllowOverride None
|
||||
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
Require all granted
|
||||
Satisfy Any
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
Alias /zm /usr/share/zoneminder/www
|
||||
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
php_flag register_globals off
|
||||
Options +Indexes +FollowSymLinks
|
||||
AllowOverride All
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
||||
</IfModule>
|
||||
Require all granted
|
||||
Satisfy Any
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
|
||||
</Directory>
|
||||
`;
|
||||
if ( $$opts{protocol} eq 'https' ) {
|
||||
$template .= qq`
|
||||
SSLCertificateFile /etc/letsencrypt/live/$$opts{server_name}/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/$$opts{server_name}/privkey.pem
|
||||
Include /etc/letsencrypt/options-ssl-apache.conf
|
||||
`;
|
||||
}
|
||||
$template .= qq`
|
||||
</VirtualHost>
|
||||
`;
|
||||
|
||||
|
||||
if ( open( F, "> $$opts{output}" ) ) {
|
||||
binmode F;
|
||||
print F $template;
|
||||
close F;
|
||||
} else {
|
||||
die "Error opening $$opts{output}, Reason: $!";
|
||||
} # end if
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -368,7 +368,7 @@ function getNearEvents() {
|
|||
else
|
||||
$midSql = '';
|
||||
|
||||
$sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where ".dbEscape($sortColumn)." ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
|
||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
|
||||
$result = dbQuery( $sql );
|
||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||
if ( $id == $eventId ) {
|
||||
|
@ -377,7 +377,7 @@ function getNearEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
$sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
|
||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
|
||||
$result = dbQuery( $sql );
|
||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||
if ( $id == $eventId ) {
|
||||
|
@ -389,6 +389,8 @@ function getNearEvents() {
|
|||
$result = array( 'EventId'=>$eventId );
|
||||
$result['PrevEventId'] = empty($prevEvent)?0:$prevEvent['Id'];
|
||||
$result['NextEventId'] = empty($nextEvent)?0:$nextEvent['Id'];
|
||||
$result['PrevEventStartTime'] = empty($prevEvent)?0:$prevEvent['StartTime'];
|
||||
$result['NextEventStartTime'] = empty($nextEvent)?0:$nextEvent['StartTime'];
|
||||
$result['PrevEventDefVideoPath'] = empty($prevEvent)?0:(getEventDefaultVideoPath($prevEvent));
|
||||
$result['NextEventDefVideoPath'] = empty($nextEvent)?0:(getEventDefaultVideoPath($nextEvent));
|
||||
return( $result );
|
||||
|
|
|
@ -3,46 +3,42 @@
|
|||
define( "MSG_TIMEOUT", ZM_WEB_AJAX_TIMEOUT );
|
||||
define( "MSG_DATA_SIZE", 4+256 );
|
||||
|
||||
if ( !($_REQUEST['connkey'] && $_REQUEST['command']) )
|
||||
{
|
||||
ajaxError( "Unexpected received message type '$type'" );
|
||||
if ( !($_REQUEST['connkey'] && $_REQUEST['command']) ) {
|
||||
ajaxError( "Unexpected received message type '$type'" );
|
||||
}
|
||||
|
||||
if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) )
|
||||
{
|
||||
ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) );
|
||||
if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) ) {
|
||||
ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) );
|
||||
}
|
||||
$locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock';
|
||||
if ( !@socket_bind( $socket, $locSockFile ) )
|
||||
{
|
||||
ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
if ( !@socket_bind( $socket, $locSockFile ) ) {
|
||||
ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
}
|
||||
|
||||
switch ( $_REQUEST['command'] )
|
||||
{
|
||||
case CMD_VARPLAY :
|
||||
Logger::Debug( "Varplaying to ".$_REQUEST['rate'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
|
||||
break;
|
||||
case CMD_ZOOMIN :
|
||||
Logger::Debug( "Zooming to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_PAN :
|
||||
Logger::Debug( "Panning to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_SCALE :
|
||||
Logger::Debug( "Scaling to ".$_REQUEST['scale'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
|
||||
break;
|
||||
case CMD_SEEK :
|
||||
Logger::Debug( "Seeking to ".$_REQUEST['offset'] );
|
||||
$msg = pack( "lcN", MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
|
||||
break;
|
||||
default :
|
||||
$msg = pack( "lc", MSG_CMD, $_REQUEST['command'] );
|
||||
break;
|
||||
switch ( $_REQUEST['command'] ) {
|
||||
case CMD_VARPLAY :
|
||||
Logger::Debug( "Varplaying to ".$_REQUEST['rate'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
|
||||
break;
|
||||
case CMD_ZOOMIN :
|
||||
Logger::Debug( "Zooming to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_PAN :
|
||||
Logger::Debug( "Panning to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_SCALE :
|
||||
Logger::Debug( "Scaling to ".$_REQUEST['scale'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
|
||||
break;
|
||||
case CMD_SEEK :
|
||||
Logger::Debug( "Seeking to ".$_REQUEST['offset'] );
|
||||
$msg = pack( "lcN", MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
|
||||
break;
|
||||
default :
|
||||
$msg = pack( "lc", MSG_CMD, $_REQUEST['command'] );
|
||||
break;
|
||||
}
|
||||
|
||||
$remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'s.sock';
|
||||
|
@ -64,98 +60,88 @@ $wSockets = NULL;
|
|||
$eSockets = NULL;
|
||||
$numSockets = @socket_select( $rSockets, $wSockets, $eSockets, intval(MSG_TIMEOUT/1000), (MSG_TIMEOUT%1000)*1000 );
|
||||
|
||||
if ( $numSockets === false )
|
||||
{
|
||||
ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) );
|
||||
}
|
||||
else if ( $numSockets < 0 )
|
||||
{
|
||||
ajaxError( "Socket closed $remSockFile" );
|
||||
}
|
||||
else if ( $numSockets == 0 )
|
||||
{
|
||||
ajaxError( "Timed out waiting for msg $remSockFile" );
|
||||
}
|
||||
else if ( $numSockets > 0 )
|
||||
{
|
||||
if ( count($rSockets) != 1 )
|
||||
ajaxError( "Bogus return from select, ".count($rSockets)." sockets available" );
|
||||
if ( $numSockets === false ) {
|
||||
ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) );
|
||||
} else if ( $numSockets < 0 ) {
|
||||
ajaxError( "Socket closed $remSockFile" );
|
||||
} else if ( $numSockets == 0 ) {
|
||||
ajaxError( "Timed out waiting for msg $remSockFile" );
|
||||
} else if ( $numSockets > 0 ) {
|
||||
if ( count($rSockets) != 1 )
|
||||
ajaxError( "Bogus return from select, ".count($rSockets)." sockets available" );
|
||||
}
|
||||
|
||||
switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) )
|
||||
{
|
||||
case -1 :
|
||||
{
|
||||
ajaxError( "socket_recvfrom( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
break;
|
||||
}
|
||||
case 0 :
|
||||
{
|
||||
ajaxError( "No data to read from socket" );
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
if ( $nbytes != MSG_DATA_SIZE )
|
||||
ajaxError( "Got unexpected message size, got $nbytes, expected ".MSG_DATA_SIZE );
|
||||
break;
|
||||
}
|
||||
switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) ) {
|
||||
case -1 :
|
||||
{
|
||||
ajaxError( "socket_recvfrom( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
break;
|
||||
}
|
||||
case 0 :
|
||||
{
|
||||
ajaxError( "No data to read from socket" );
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
if ( $nbytes != MSG_DATA_SIZE )
|
||||
ajaxError( "Got unexpected message size, got $nbytes, expected ".MSG_DATA_SIZE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$data = unpack( "ltype", $msg );
|
||||
switch ( $data['type'] )
|
||||
{
|
||||
case MSG_DATA_WATCH :
|
||||
{
|
||||
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
|
||||
$data['fps'] = round( $data['fps'], 2 );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['delay'] = round( $data['delay'], 2 );
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {
|
||||
$data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
ajaxResponse( array( 'status'=>$data ) );
|
||||
break;
|
||||
switch ( $data['type'] ) {
|
||||
case MSG_DATA_WATCH :
|
||||
{
|
||||
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
|
||||
$data['fps'] = round( $data['fps'], 2 );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['delay'] = round( $data['delay'], 2 );
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {
|
||||
$data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
case MSG_DATA_EVENT :
|
||||
{
|
||||
$data = unpack( "ltype/ievent/iprogress/irate/izoom/Cpaused", $msg );
|
||||
//$data['progress'] = sprintf( "%.2f", $data['progress'] );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {
|
||||
$data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
ajaxResponse( array( 'status'=>$data ) );
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
ajaxError( "Unexpected received message type '$type'" );
|
||||
ajaxResponse( array( 'status'=>$data ) );
|
||||
break;
|
||||
}
|
||||
case MSG_DATA_EVENT :
|
||||
{
|
||||
$data = unpack( "ltype/ievent/iprogress/irate/izoom/Cpaused", $msg );
|
||||
//$data['progress'] = sprintf( "%.2f", $data['progress'] );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {
|
||||
$data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
ajaxResponse( array( 'status'=>$data ) );
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
ajaxError( "Unexpected received message type '$type'" );
|
||||
}
|
||||
}
|
||||
|
||||
ajaxError( 'Unrecognised action or insufficient permissions' );
|
||||
|
||||
function ajaxCleanup()
|
||||
{
|
||||
global $socket, $locSockFile;
|
||||
if ( !empty( $socket ) )
|
||||
@socket_close( $socket );
|
||||
if ( !empty( $locSockFile ) )
|
||||
@unlink( $locSockFile );
|
||||
function ajaxCleanup() {
|
||||
global $socket, $locSockFile;
|
||||
if ( !empty( $socket ) )
|
||||
@socket_close( $socket );
|
||||
if ( !empty( $locSockFile ) )
|
||||
@unlink( $locSockFile );
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# Define the line ending behavior of the different file extensions
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files we want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.php text
|
||||
*.default text
|
||||
*.ctp text
|
||||
*.sql text
|
||||
*.md text
|
||||
*.po text
|
||||
*.js text
|
||||
*.css text
|
||||
*.ini text
|
||||
*.properties text
|
||||
*.txt text
|
||||
*.xml text
|
||||
*.yml text
|
||||
.htaccess text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.bat eol=crlf
|
||||
|
||||
# Declare files that will always have LF line endings on checkout.
|
||||
*.pem eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mo binary
|
|
@ -1,21 +0,0 @@
|
|||
# User specific & automatically generated files #
|
||||
#################################################
|
||||
/app/Config/database.php
|
||||
/app/tmp
|
||||
/lib/Cake/Console/Templates/skel/tmp/
|
||||
/plugins
|
||||
/vendors
|
||||
/build
|
||||
/dist
|
||||
/tags
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
class Group {
|
||||
|
||||
public $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
'ParentId' => null,
|
||||
'MonitorIds' => '',
|
||||
);
|
||||
|
||||
public function __construct( $IdOrRow=NULL ) {
|
||||
$row = NULL;
|
||||
if ( $IdOrRow ) {
|
||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
||||
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||
if ( ! $row ) {
|
||||
Error('Unable to load Group record for Id=' . $IdOrRow );
|
||||
}
|
||||
} elseif ( is_array( $IdOrRow ) ) {
|
||||
$row = $IdOrRow;
|
||||
} else {
|
||||
$backTrace = debug_backtrace();
|
||||
$file = $backTrace[1]['file'];
|
||||
$line = $backTrace[1]['line'];
|
||||
Error("Unknown argument passed to Group Constructor from $file:$line)");
|
||||
Error("Unknown argument passed to Group Constructor ($IdOrRow)");
|
||||
return;
|
||||
}
|
||||
} # end if isset($IdOrRow)
|
||||
|
||||
if ( $row ) {
|
||||
foreach ($row as $k => $v) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
}
|
||||
} // end function __construct
|
||||
|
||||
public function __call( $fn, array $args ) {
|
||||
if ( count( $args ) ) {
|
||||
$this->{$fn} = $args[0];
|
||||
}
|
||||
if ( array_key_exists( $fn, $this ) ) {
|
||||
return $this->{$fn};
|
||||
} else if ( array_key_exists( $fn, $this->defaults ) ) {
|
||||
$this->{$fn} = $this->defaults{$fn};
|
||||
return $this->{$fn};
|
||||
} else {
|
||||
|
||||
$backTrace = debug_backtrace();
|
||||
$file = $backTrace[1]['file'];
|
||||
$line = $backTrace[1]['line'];
|
||||
Warning( "Unknown function call Group->$fn from $file:$line" );
|
||||
}
|
||||
}
|
||||
|
||||
public static function find_all( $parameters = null ) {
|
||||
$filters = array();
|
||||
$sql = 'SELECT * FROM Groups ';
|
||||
$values = array();
|
||||
|
||||
if ( $parameters ) {
|
||||
$fields = array();
|
||||
$sql .= 'WHERE ';
|
||||
foreach ( $parameters as $field => $value ) {
|
||||
if ( $value == null ) {
|
||||
$fields[] = $field.' IS NULL';
|
||||
} else if ( is_array( $value ) ) {
|
||||
$func = function(){return '?';};
|
||||
$fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')';
|
||||
$values += $value;
|
||||
|
||||
} else {
|
||||
$fields[] = $field.'=?';
|
||||
$values[] = $value;
|
||||
}
|
||||
}
|
||||
$sql .= implode(' AND ', $fields );
|
||||
}
|
||||
$sql .= ' ORDER BY Name';
|
||||
$result = dbQuery($sql, $values);
|
||||
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Group');
|
||||
foreach ( $results as $row => $obj ) {
|
||||
$filters[] = $obj;
|
||||
}
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
dbQuery( 'DELETE FROM Groups WHERE Id = ?', array($this->{'Id'}) );
|
||||
} # end function delete()
|
||||
|
||||
public function set( $data ) {
|
||||
foreach ($data as $k => $v) {
|
||||
if ( is_array( $v ) ) {
|
||||
$this->{$k} = $v;
|
||||
} else if ( is_string( $v ) ) {
|
||||
$this->{$k} = trim( $v );
|
||||
} else if ( is_integer( $v ) ) {
|
||||
$this->{$k} = $v;
|
||||
} else if ( is_bool( $v ) ) {
|
||||
$this->{$k} = $v;
|
||||
} else {
|
||||
Error( "Unknown type $k => $v of var " . gettype( $v ) );
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
public function depth( $new = null ) {
|
||||
if ( isset($new) ) {
|
||||
$this->{'depth'} = $new;
|
||||
}
|
||||
if ( ! array_key_exists( 'depth', $this ) or ( $this->{'depth'} == null ) ) {
|
||||
$this->{'depth'} = 1;
|
||||
if ( $this->{'ParentId'} != null ) {
|
||||
$Parent = new Group( $this->{'ParentId'} );
|
||||
$this->{'depth'} += $Parent->depth();
|
||||
}
|
||||
}
|
||||
return $this->{'depth'};
|
||||
} // end public function depth
|
||||
|
||||
public static function get_group_dropdowns() {
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = 0;
|
||||
$depth = 0;
|
||||
$groups = array();
|
||||
$parent_group_ids = null;
|
||||
while(1) {
|
||||
$Groups = Group::find_all( array('ParentId'=>$parent_group_ids) );
|
||||
if ( ! count( $Groups ) )
|
||||
break;
|
||||
|
||||
$parent_group_ids = array();
|
||||
$selected_group_id = 0;
|
||||
if ( isset($_REQUEST['group'.$depth]) and $_REQUEST['group'.$depth] > 0 ) {
|
||||
$selected_group_id = $group_id = $_REQUEST['group'.$depth];
|
||||
} else if ( isset($_COOKIE['zmGroup'.$depth] ) and $_COOKIE['zmGroup'.$depth] > 0 ) {
|
||||
$selected_group_id = $group_id = $_COOKIE['zmGroup'.$depth];
|
||||
}
|
||||
|
||||
foreach ( $Groups as $Group ) {
|
||||
if ( ! isset( $groups[$depth] ) ) {
|
||||
$groups[$depth] = array(0=>'All');
|
||||
}
|
||||
$groups[$depth][$Group->Id()] = $Group->Name();
|
||||
if ( $selected_group_id and ( $selected_group_id == $Group->Id() ) )
|
||||
$parent_group_ids[] = $Group->Id();
|
||||
}
|
||||
|
||||
echo htmlSelect( 'group'.$depth, $groups[$depth], $selected_group_id, "changeGroup(this,$depth);" );
|
||||
if ( ! count($parent_group_ids) ) break;
|
||||
$depth += 1;
|
||||
}
|
||||
|
||||
return $group_id;
|
||||
} # end public static function get_group_dropdowns()
|
||||
|
||||
public static function get_group_sql( $group_id ) {
|
||||
$groupSql = '';
|
||||
if ( $group_id ) {
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id=?', NULL, array($group_id) ) ) {
|
||||
$groupIds = array();
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = explode( ',', $group['MonitorIds'] );
|
||||
|
||||
foreach ( dbFetchAll( 'SELECT MonitorIds FROM Groups WHERE ParentId = ?', NULL, array($group_id) ) as $group )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
}
|
||||
$groupSql = " find_in_set( Id, '".implode( ',', $groupIds )."' )";
|
||||
}
|
||||
return $groupSql;
|
||||
} # end public static function get_group_sql( $group_id )
|
||||
} # end class Group
|
||||
?>
|
|
@ -174,10 +174,13 @@ private $control_fields = array(
|
|||
public function getStreamSrc( $args, $querySep='&' ) {
|
||||
if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) {
|
||||
$Server = new Server( $this->{'ServerId'} );
|
||||
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname().ZM_PATH_ZMS;
|
||||
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname();
|
||||
} else {
|
||||
$streamSrc = ZM_BASE_URL.ZM_PATH_ZMS;
|
||||
$streamSrc = ZM_BASE_URL;
|
||||
}
|
||||
if ( ZM_MIN_STREAMING_PORT )
|
||||
$streamSrc .= ':'. (ZM_MIN_STREAMING_PORT+$this->{'Id'});
|
||||
$streamSrc .= ZM_PATH_ZMS;
|
||||
|
||||
$args['monitor'] = $this->{'Id'};
|
||||
|
||||
|
|
|
@ -605,11 +605,13 @@ Warning("Addterm");
|
|||
if ( canEdit( 'Groups' ) ) {
|
||||
if ( $action == 'group' ) {
|
||||
# Should probably verfy that each monitor id is a valid monitor, that we have access to. HOwever at the moment, you have to have System permissions to do this
|
||||
$monitors = empty( $_POST['newGroup']['MonitorIds'] ) ? NULL : implode(',', $_POST['newGroup']['MonitorIds']);
|
||||
$monitors = empty( $_POST['newGroup']['MonitorIds'] ) ? '' : implode(',', $_POST['newGroup']['MonitorIds'] );
|
||||
if ( !empty($_POST['gid']) ) {
|
||||
dbQuery( "UPDATE Groups SET Name=?, MonitorIds=? WHERE Id=?", array($_POST['newGroup']['Name'], $monitors, $_POST['gid']) );
|
||||
dbQuery( 'UPDATE Groups SET Name=?, ParentId=?, MonitorIds=? WHERE Id=?',
|
||||
array($_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $monitors, $_POST['gid']) );
|
||||
} else {
|
||||
dbQuery( "INSERT INTO Groups SET Name=?, MonitorIds=?", array( $_POST['newGroup']['Name'], $monitors ) );
|
||||
dbQuery( 'INSERT INTO Groups SET Name=?, ParentId=?, MonitorIds=?',
|
||||
array( $_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $monitors ) );
|
||||
}
|
||||
$view = 'none';
|
||||
}
|
||||
|
|
|
@ -46,11 +46,14 @@ $configSubFolder = ZM_CONFIG_SUBDIR;
|
|||
if ( is_dir($configSubFolder) ) {
|
||||
if ( is_readable($configSubFolder) ) {
|
||||
foreach ( glob("$configSubFolder/*.conf") as $filename ) {
|
||||
error_log("processing $filename");
|
||||
$configvals = array_replace($configvals, process_configfile($filename) );
|
||||
}
|
||||
} else {
|
||||
error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." );
|
||||
}
|
||||
} else {
|
||||
error_log( "WARNING: ZoneMinder configuration subfolder found but is not a directory. Check $configSubFolder." );
|
||||
}
|
||||
|
||||
# Now that our array our finalized, define each key => value
|
||||
|
|
|
@ -127,6 +127,10 @@ function dbQuery( $sql, $params=NULL ) {
|
|||
} else {
|
||||
$result = $dbConn->query( $sql );
|
||||
}
|
||||
//if ( $params )
|
||||
//Warning("SQL: $sql" . implode(',',$params));
|
||||
//else
|
||||
//Warning("SQL: $sql" );
|
||||
} catch(PDOException $e) {
|
||||
Fatal( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."'" );
|
||||
}
|
||||
|
|
|
@ -538,7 +538,7 @@ function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1,
|
|||
$popupParms = "'".$url."', '".$winName."', '".$winSize[0]."', ".$winSize[1].", ".$winSize[2];
|
||||
else
|
||||
$popupParms = "'".$url."', '".$winName."', '".$winSize."'";
|
||||
$string = '<input class="btn btn-primary" type="button" value="'.$buttonValue.'" onclick="createPopup( '.$popupParms.' ); return( false );"'.($condition?'':' disabled="disabled"').($options?(' '.$options):'').'/>';
|
||||
$string = '<input type="button" value="'.$buttonValue.'" onclick="createPopup( '.$popupParms.' ); return( false );"'.($condition?'':' disabled="disabled"').($options?(' '.$options):'').'/>';
|
||||
return( $string );
|
||||
}
|
||||
|
||||
|
@ -557,6 +557,9 @@ function htmlSelect( $name, $contents, $values, $behaviours=false ) {
|
|||
|
||||
$html = "<select name=\"$name\" id=\"$name\"$behaviourText>";
|
||||
foreach ( $contents as $value=>$text ) {
|
||||
//for ( $i = 0; $i < count($contents); $i +=2 ) {
|
||||
//$value = $contents[$i];
|
||||
//$text = $contents[$i+1];
|
||||
$selected = is_array( $values ) ? in_array( $value, $values ) : $value==$values;
|
||||
$html .= "<option value=\"$value\"".($selected?" selected=\"selected\"":'').">$text</option>";
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ require_once( 'includes/logger.php' );
|
|||
require_once( 'includes/Server.php' );
|
||||
require_once( 'includes/Storage.php' );
|
||||
require_once( 'includes/Event.php' );
|
||||
require_once( 'includes/Group.php' );
|
||||
require_once( 'includes/Monitor.php' );
|
||||
|
||||
if ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ) {
|
||||
|
@ -194,7 +195,7 @@ isset($view) || $view = NULL;
|
|||
isset($request) || $request = NULL;
|
||||
isset($action) || $action = NULL;
|
||||
|
||||
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' ) {
|
||||
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') {
|
||||
require_once( 'includes/csrf/csrf-magic.php' );
|
||||
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||
csrf_check();
|
||||
|
|
|
@ -88,6 +88,7 @@ $SLANG = array(
|
|||
'AddNewControl' => 'Add New Control',
|
||||
'AddNewMonitor' => 'Add New Monitor',
|
||||
'AddNewServer' => 'Add New Server',
|
||||
'AddNewStorage' => 'Add New Storage',
|
||||
'AddNewUser' => 'Add New User',
|
||||
'AddNewZone' => 'Add New Zone',
|
||||
'Alarm' => 'Alarm',
|
||||
|
@ -594,13 +595,13 @@ $SLANG = array(
|
|||
'Record' => 'Record',
|
||||
'RefImageBlendPct' => 'Reference Image Blend %ge',
|
||||
'Refresh' => 'Refresh',
|
||||
'RemoteHostName' => 'Remote Host Name',
|
||||
'RemoteHostPath' => 'Remote Host Path',
|
||||
'RemoteHostSubPath' => 'Remote Host SubPath',
|
||||
'RemoteHostPort' => 'Remote Host Port',
|
||||
'RemoteImageColours' => 'Remote Image Colours',
|
||||
'RemoteMethod' => 'Remote Method',
|
||||
'RemoteProtocol' => 'Remote Protocol',
|
||||
'RemoteHostName' => 'Host Name',
|
||||
'RemoteHostPath' => 'Path',
|
||||
'RemoteHostSubPath' => 'SubPath',
|
||||
'RemoteHostPort' => 'Port',
|
||||
'RemoteImageColours' => 'Image Colours',
|
||||
'RemoteMethod' => 'Method',
|
||||
'RemoteProtocol' => 'Protocol',
|
||||
'Remote' => 'Remote',
|
||||
'Rename' => 'Rename',
|
||||
'ReplayAll' => 'All Events',
|
||||
|
@ -644,8 +645,8 @@ $SLANG = array(
|
|||
'ShowTimeline' => 'Show Timeline',
|
||||
'SignalCheckColour' => 'Signal Check Colour',
|
||||
'Size' => 'Size',
|
||||
'SkinDescription' => 'Change the default skin for this computer',
|
||||
'CSSDescription' => 'Change the default css for this computer',
|
||||
'SkinDescription' => 'Change the skin for this session',
|
||||
'CSSDescription' => 'Change the css for this session',
|
||||
'Sleep' => 'Sleep',
|
||||
'SortAsc' => 'Asc',
|
||||
'SortBy' => 'Sort by',
|
||||
|
|
|
@ -106,32 +106,32 @@
|
|||
#monitorStatus #monitorState {
|
||||
}
|
||||
|
||||
#dvrControls {
|
||||
.dvrControls {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#dvrControls input {
|
||||
.dvrControls input {
|
||||
height: 20px;
|
||||
width: 28px;
|
||||
padding-bottom: 3px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
#dvrControls input[disabled=disabled] {
|
||||
.dvrControls input[disabled=disabled] {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
#dvrControls input.active {
|
||||
.dvrControls input.active {
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
#dvrControls input.inactive {
|
||||
.dvrControls input.inactive {
|
||||
border: 1px solid green;
|
||||
}
|
||||
|
||||
#dvrControls input.unavail {
|
||||
.dvrControls input.unavail {
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,3 +33,6 @@
|
|||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -492,16 +492,13 @@ input[type=submit]:disabled {
|
|||
|
||||
#consoleTable td, #consoleTable th {
|
||||
padding: 5px;
|
||||
border-bottom: 2px solid #f2f2f2;
|
||||
border-bottom: 1px solid #000000;
|
||||
}
|
||||
|
||||
#consoleTable input[type=button] {
|
||||
margin-right: 3px !important;
|
||||
}
|
||||
|
||||
#consoleTable tfoot {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.navbar{
|
||||
margin-bottom: 0 !important;
|
||||
|
@ -537,3 +534,8 @@ input[type=submit]:disabled {
|
|||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
.table-striped > tbody > tr:nth-of-type(2n+1) {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,32 +89,32 @@
|
|||
#monitorStatus #monitorState {
|
||||
}
|
||||
|
||||
#dvrControls {
|
||||
.dvrControls {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#dvrControls input {
|
||||
.dvrControls input {
|
||||
height: 20px;
|
||||
width: 28px;
|
||||
padding-bottom: 3px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
#dvrControls input[disabled=disabled] {
|
||||
.dvrControls input[disabled=disabled] {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
#dvrControls input.active {
|
||||
.dvrControls input.active {
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
#dvrControls input.inactive {
|
||||
.dvrControls input.inactive {
|
||||
border: 1px solid green;
|
||||
}
|
||||
|
||||
#dvrControls input.unavail {
|
||||
.dvrControls input.unavail {
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,3 +33,6 @@
|
|||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -94,17 +94,18 @@ label {
|
|||
|
||||
input,textarea,select,button {
|
||||
border: 1px #ccc solid;
|
||||
padding: 10px;
|
||||
padding: 5px;
|
||||
border-radius: 2px;
|
||||
font-family: inherit;
|
||||
font-weight: 400;
|
||||
font-size: 100%;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/*
|
||||
input[type=text], input[type=password], input[type="url"], textarea, select {
|
||||
padding: 1px;
|
||||
}
|
||||
*/
|
||||
|
||||
input.noborder {
|
||||
border: 0;
|
||||
|
|
|
@ -98,36 +98,36 @@
|
|||
#monitorStatus #monitorState {
|
||||
}
|
||||
|
||||
#dvrControls {
|
||||
.dvrControls {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#dvrControls input {
|
||||
.dvrControls input {
|
||||
padding: 10px 10px;
|
||||
width: 50px;
|
||||
margin: 0 3px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
#dvrControls input[disabled=disabled] {
|
||||
.dvrControls input[disabled=disabled] {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
#dvrControls input.active {
|
||||
.dvrControls input.active {
|
||||
border: 0;
|
||||
background-color: #2ecc71;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#dvrControls input.inactive {
|
||||
.dvrControls input.inactive {
|
||||
border: 0;
|
||||
background-color: #e67e22;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#dvrControls input.unavail {
|
||||
.dvrControls input.unavail {
|
||||
background-color: #ccc;
|
||||
border: 0;
|
||||
cursor: default;
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#SpeedDiv label {
|
||||
margin: 0;
|
||||
}
|
||||
#DateTimeDiv {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
#scaleslideroutput,
|
||||
#speedslideroutput {
|
||||
|
@ -29,7 +32,9 @@
|
|||
|
||||
#monitors {
|
||||
position:relative;
|
||||
background-color:black;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,15 @@ function xhtmlHeaders( $file, $title ) {
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
|
||||
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
|
||||
<link rel="shortcut icon" href="graphics/favicon.ico"/>
|
||||
<?php
|
||||
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
||||
echo "<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>";
|
||||
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>";
|
||||
} else {
|
||||
echo '<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>';
|
||||
echo '<link rel="shortcut icon" href="graphics/favicon.ico"/>';
|
||||
}
|
||||
?>
|
||||
<link rel="stylesheet" href="css/reset.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/overlay.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
|
||||
|
@ -128,6 +135,10 @@ function xhtmlHeaders( $file, $title ) {
|
|||
if ( $cssJsFile ) {
|
||||
?>
|
||||
<script type="text/javascript" src="<?php echo $cssJsFile ?>"></script>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<script type="text/javascript" src="skins/classic/js/classic.js"></script>
|
||||
<?php } ?>
|
||||
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
|
||||
<script type="text/javascript" src="js/logger.js"></script>
|
||||
|
@ -144,53 +155,24 @@ function xhtmlHeaders( $file, $title ) {
|
|||
|
||||
function getNavBarHTML() {
|
||||
|
||||
$group = NULL;
|
||||
if ( ! empty($_COOKIE['zmGroup']) ) {
|
||||
if ( $group = dbFetchOne( 'select * from Groups where Id = ?', NULL, array($_COOKIE['zmGroup'])) )
|
||||
$groupIds = array_flip(explode( ',', $group['MonitorIds'] ));
|
||||
}
|
||||
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
# Used to determine if the Cycle button should be made available
|
||||
$cycleCount = 0;
|
||||
$monitors = dbFetchAll( "select * from Monitors order by Sequence asc" );
|
||||
global $displayMonitors;
|
||||
$displayMonitors = array();
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $monitors[$i]['Function'] != 'None' ) {
|
||||
$cycleCount++;
|
||||
$scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth;
|
||||
if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight;
|
||||
}
|
||||
$displayMonitors[] = $monitors[$i];
|
||||
}
|
||||
|
||||
$cycleWidth = $maxWidth;
|
||||
$cycleHeight = $maxHeight;
|
||||
|
||||
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
|
||||
|
||||
|
||||
ob_start();
|
||||
global $CLANG;
|
||||
global $VLANG;
|
||||
global $CLANG;
|
||||
global $VLANG;
|
||||
global $running;
|
||||
if ( $running == null )
|
||||
$running = daemonCheck();
|
||||
$status = $running?translate('Running'):translate('Stopped');
|
||||
global $user;
|
||||
global $bwArray;
|
||||
global $view;
|
||||
?>
|
||||
<noscript>
|
||||
<div style="background-color:red;color:white;font-size:x-large;">
|
||||
ZoneMinder requires Javascript. Please enable Javascript in your browser for this site.
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-static-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
|
@ -213,20 +195,19 @@ function getNavBarHTML() {
|
|||
<?php if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
||||
<li><a href="?view=devices">Devices</a></li>
|
||||
<?php } ?>
|
||||
<li><?php echo makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'Groups' ) ); ?></li>
|
||||
<li><a href="?view=filter">Filters</a></li>
|
||||
<li><a href="?view=groups"<?php echo $view=='groups'?' class="selected"':''?>><?php echo translate('Groups') ?></a></li>
|
||||
<li><a href="?view=filter"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
|
||||
|
||||
<?php
|
||||
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
|
||||
if ( canView( 'Stream' ) && $cycleCount > 1 ) {
|
||||
if ( canView( 'Stream' ) ) {
|
||||
?>
|
||||
<li><?php echo makePopupLink( '?view=cycle&group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?></li>
|
||||
<li><?php echo makePopupLink( '?view=montage&group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?></li>
|
||||
<li><a href="?view=cycle"<?php echo $view=='cycle'?' class="selected"':''?>><?php echo translate('Cycle') ?></a></li>
|
||||
<li><a href="?view=montage"<?php echo $view=='montage'?' class="selected"':''?>><?php echo translate('Montage') ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ( canView('Events') ) {
|
||||
?>
|
||||
<li><?php echo makePopupLink( '?view=montagereview&group='.$cycleGroup, 'zmMontageReview'.$cycleGroup, 'montagereview', translate('MontageReview') ) ?></li>
|
||||
<li><a href="?view=montagereview"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
@ -248,7 +229,7 @@ function getNavBarHTML() {
|
|||
</div> <!-- End .container-fluid -->
|
||||
<div class="container-fluid">
|
||||
<div class="pull-left">
|
||||
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?php echo translate('BandwidthHead') ?>
|
||||
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']] . ' ' . translate('BandwidthHead'), ($user && $user['MaxBandwidth'] != 'low' ) ) ?>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?>
|
||||
|
|
|
@ -45,6 +45,10 @@ function newWindow( url, name, width, height ) {
|
|||
}
|
||||
|
||||
function getPopupSize( tag, width, height ) {
|
||||
if ( typeof popupSizes == 'undefined' ) {
|
||||
Error( "Can't find any window sizes" );
|
||||
return( { 'width': 0, 'height': 0 } );
|
||||
}
|
||||
var popupSize = Object.clone( popupSizes[tag] );
|
||||
if ( !popupSize ) {
|
||||
Error( "Can't find window size for tag '"+tag+"'" );
|
||||
|
@ -83,7 +87,6 @@ function getPopupSize( tag, width, height ) {
|
|||
Warning( "Adjusting to minimum height ("+popupSize.minHeight+") when getting popup size for tag '"+tag+"' because calculated height is " + popupSize.height );
|
||||
popupSize.height = popupSize.minHeight;
|
||||
}
|
||||
Debug( popupSize );
|
||||
return( popupSize );
|
||||
}
|
||||
|
||||
|
@ -226,6 +229,14 @@ function submitTab( tab ) {
|
|||
form.submit();
|
||||
}
|
||||
|
||||
function toggleCheckbox( element, name ) {
|
||||
var form = element.form;
|
||||
var checked = element.checked;
|
||||
for (var i = 0; i < form.elements.length; i++)
|
||||
if (form.elements[i].name.indexOf(name) == 0)
|
||||
form.elements[i].checked = checked;
|
||||
}
|
||||
|
||||
function configureDeleteButton( element ) {
|
||||
var form = element.form;
|
||||
var checked = element.checked;
|
||||
|
@ -293,3 +304,14 @@ function addVideoTimingTrack(video, LabelFormat, monitorName, duration, startTim
|
|||
track.src = 'data:plain/text;charset=utf-8,'+encodeURIComponent(webvttdata);
|
||||
video.appendChild(track);
|
||||
}
|
||||
|
||||
function changeGroup( e, depth ) {
|
||||
var group_id = $('group'+depth).get('value');
|
||||
Cookie.write( 'zmGroup'+depth, group_id, { duration: 10*365 } );
|
||||
window.location = window.location;
|
||||
}
|
||||
function changeMonitor( e ) {
|
||||
var monitor_id = e.value;
|
||||
Cookie.write( 'zmMonitorId', monitor_id, { duration: 10*365 } );
|
||||
window.location = window.location;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ var focusWindow = <?php echo !empty($focusWindow)?'true':'false' ?>;
|
|||
|
||||
var imagePrefix = "<?php echo viewImagePath( "", '&' ) ?>";
|
||||
|
||||
var auth_hash;
|
||||
<?php if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { ?>
|
||||
var auth_hash = '<?php echo isset($_SESSION['AuthHash']) ? $_SESSION['AuthHash'] : ''; ?>';
|
||||
auth_hash = '<?php echo isset($_SESSION['AuthHash']) ? $_SESSION['AuthHash'] : ''; ?>';
|
||||
<?php } ?>
|
||||
|
|
|
@ -19,106 +19,85 @@
|
|||
//
|
||||
|
||||
$servers = Server::find_all();
|
||||
require_once('includes/Storage.php');
|
||||
$storage_areas = Storage::find_all();
|
||||
$StorageById = array();
|
||||
foreach ( $storage_areas as $S ) {
|
||||
$StorageById[$S->Id()] = $S;
|
||||
}
|
||||
|
||||
$show_storage_areas = count($storage_areas) > 1 and canEdit( 'System' ) ? 1 : 0;
|
||||
if ( $running == null )
|
||||
$running = daemonCheck();
|
||||
|
||||
$eventCounts = array(
|
||||
array(
|
||||
'title' => translate('Events'),
|
||||
'filter' => array(
|
||||
'Query' => array (
|
||||
'terms' => array()
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
array(
|
||||
'title' => translate('Events'),
|
||||
'filter' => array(
|
||||
'Query' => array (
|
||||
'terms' => array()
|
||||
)
|
||||
),
|
||||
array(
|
||||
'title' => translate('Hour'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 hour' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Hour'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 hour' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'title' => translate('Day'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Day'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'title' => translate('Week'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-7 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Week'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-7 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'title' => translate('Month'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 month' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Month'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 month' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'title' => translate('Archived'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'Archived', 'op' => '=', 'val' => '1' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Archived'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'Archived', 'op' => '=', 'val' => '1' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
);
|
||||
|
||||
$displayMonitors = NULL;
|
||||
|
||||
# Also populates displayMonitors
|
||||
$navbar = getNavBarHTML();
|
||||
$zoneCount = 0;
|
||||
|
||||
for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
|
||||
$monitor = $displayMonitors[$i];
|
||||
$monitor['zmc'] = zmcStatus( $monitor );
|
||||
$monitor['zma'] = zmaStatus( $monitor );
|
||||
$monitor['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitor['Id']) );
|
||||
$counts = array();
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
||||
parseFilter( $filter );
|
||||
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) as EventCount$j";
|
||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||
}
|
||||
$sql = 'select '.join($counts,', ').' from Events as E where MonitorId = ?';
|
||||
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
||||
if ( $counts )
|
||||
$displayMonitors[$i] = $monitor = array_merge( $monitor, $counts );
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
||||
}
|
||||
$zoneCount += $monitor['ZoneCount'];
|
||||
}
|
||||
|
||||
noCacheHeaders();
|
||||
|
||||
|
@ -137,6 +116,79 @@ xhtmlHeaders( __FILE__, translate('Console') );
|
|||
<input type="hidden" name="action" value=""/>
|
||||
|
||||
<?php echo $navbar ?>
|
||||
<div class="controlHeader">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
?>
|
||||
</span>
|
||||
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label>
|
||||
<?php
|
||||
|
||||
$monitor_id = 0;
|
||||
if ( isset( $_REQUEST['monitor_id'] ) ) {
|
||||
$monitor_id = $_REQUEST['monitor_id'];
|
||||
} else if ( isset($_COOKIE['zmMonitorId']) ) {
|
||||
$monitor_id = $_COOKIE['zmMonitorId'];
|
||||
}
|
||||
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
# Used to determine if the Cycle button should be made available
|
||||
|
||||
$monitors = dbFetchAll( 'SELECT * FROM Monitors'.($groupSql?' WHERE '.$groupSql:'').' ORDER BY Sequence ASC' );
|
||||
$displayMonitors = array();
|
||||
$monitors_dropdown = array(''=>'All');
|
||||
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( $monitor_id and ( $monitors[$i]['Id'] != $monitor_id ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $monitors[$i]['Function'] != 'None' ) {
|
||||
$scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth;
|
||||
if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight;
|
||||
}
|
||||
$displayMonitors[] = $monitors[$i];
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
}
|
||||
|
||||
echo htmlSelect( 'monitor_id', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') );
|
||||
|
||||
$cycleWidth = $maxWidth;
|
||||
$cycleHeight = $maxHeight;
|
||||
$zoneCount = 0;
|
||||
|
||||
for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
|
||||
$monitor = $displayMonitors[$i];
|
||||
$monitor['zmc'] = zmcStatus( $monitor );
|
||||
$monitor['zma'] = zmaStatus( $monitor );
|
||||
$monitor['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitor['Id']) );
|
||||
$counts = array();
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
||||
parseFilter( $filter );
|
||||
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) as EventCount$j";
|
||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||
}
|
||||
$sql = 'SELECt '.join($counts,', ').' from Events as E where MonitorId = ?';
|
||||
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
||||
if ( $counts )
|
||||
$displayMonitors[$i] = $monitor = array_merge( $monitor, $counts );
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
||||
}
|
||||
$zoneCount += $monitor['ZoneCount'];
|
||||
}
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<table class="table table-striped table-hover table-condensed" id="consoleTable">
|
||||
|
@ -159,7 +211,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
|
|||
<?php } ?>
|
||||
<th class="colZones"><a href="<?php echo $_SERVER['PHP_SELF'] ?>?view=zones_overview"><?php echo translate('Zones') ?></a></th>
|
||||
<?php if ( canEdit('Monitors') ) { ?>
|
||||
<th class="colMark"><?php echo translate('Mark') ?></th>
|
||||
<th class="colMark"><input type="checkbox" name="toggleCheck" value="1" onclick="toggleCheckbox( this, 'markMids[]' );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/> <?php echo translate('All') ?></th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -220,7 +272,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
echo '<td class="colSource">'. makePopupLink( '?view=monitor&mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$source.'</span>', canEdit( 'Monitors' ) ).'</td>';
|
||||
if ( $show_storage_areas ) {
|
||||
?>
|
||||
<td class="colStorage"><?php $Storage = new Storage( $monitor['StorageId'] ); echo $Storage->Name(); ?></td>
|
||||
<td class="colStorage"><?php if ( isset( $StorageById[ $monitor['StorageId'] ] ) ) { echo $StorageById[ $monitor['StorageId'] ]->Name(); } ?></td>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
@ -249,8 +301,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
<tfoot>
|
||||
<tr>
|
||||
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
|
||||
<input type="button" class="btn btn-primary" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
||||
<input type="button" class="btn btn-primary" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
|
||||
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
||||
<input type="button" 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&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
|
||||
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
|
||||
|
|
|
@ -32,14 +32,39 @@ if ( empty($_REQUEST['mode']) ) {
|
|||
$mode = validHtmlStr($_REQUEST['mode']);
|
||||
}
|
||||
|
||||
$group = '';
|
||||
$groupSql = '';
|
||||
if ( !empty($_REQUEST['group']) ) {
|
||||
$group = validInt($_REQUEST['group']);
|
||||
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($group) );
|
||||
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
|
||||
$group_id = 0;
|
||||
if ( isset($_REQUEST['group']) ) {
|
||||
$group_id = $_REQUEST['group'];
|
||||
} else if ( isset($_COOKIE['zmGroup'] ) ) {
|
||||
$group_id = $_COOKIE['zmGroup'];
|
||||
}
|
||||
|
||||
$subgroup_id = 0;
|
||||
if ( isset($_REQUEST['subgroup']) ) {
|
||||
$subgroup_id = $_REQUEST['subgroup'];
|
||||
} else if ( isset($_COOKIE['zmSubGroup'] ) ) {
|
||||
$subgroup_id = $_COOKIE['zmSubGroup'];
|
||||
}
|
||||
$groupIds = null;
|
||||
if ( $group_id ) {
|
||||
$groupIds = array();
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id = ?', NULL, array($group_id) ) )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = explode( ',', $group['MonitorIds'] );
|
||||
if ( $subgroup_id ) {
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id = ?', NULL, array($subgroup_id) ) )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
} else {
|
||||
foreach ( dbFetchAll( 'SELECT MonitorIds FROM Groups WHERE ParentId = ?', NULL, array($group_id) ) as $group )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
}
|
||||
}
|
||||
$groupSql = '';
|
||||
if ( $groupIds )
|
||||
$groupSql = " and find_in_set( Id, '".implode( ',', $groupIds )."' )";
|
||||
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None'$groupSql ORDER BY Sequence";
|
||||
$monitors = array();
|
||||
$monIdx = 0;
|
||||
|
@ -53,38 +78,59 @@ foreach( dbFetchAll( $sql ) as $row ) {
|
|||
$monitors[] = new Monitor( $row );
|
||||
}
|
||||
|
||||
$monitor = $monitors[$monIdx];
|
||||
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]->Id():$monitors[$monIdx+1]->Id();
|
||||
$montageWidth = $monitor->ScaledWidth();
|
||||
$montageHeight = $monitor->ScaledHeight();
|
||||
$widthScale = ($montageWidth*SCALE_BASE)/$monitor->Width();
|
||||
$heightScale = ($montageHeight*SCALE_BASE)/$monitor->Height();
|
||||
$scale = (int)(($widthScale<$heightScale)?$widthScale:$heightScale);
|
||||
if ( $monitors ) {
|
||||
$monitor = $monitors[$monIdx];
|
||||
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]->Id():$monitors[$monIdx+1]->Id();
|
||||
$montageWidth = $monitor->ScaledWidth();
|
||||
$montageHeight = $monitor->ScaledHeight();
|
||||
$widthScale = ($montageWidth*SCALE_BASE)/$monitor->Width();
|
||||
$heightScale = ($montageHeight*SCALE_BASE)/$monitor->Height();
|
||||
$scale = (int)(($widthScale<$heightScale)?$widthScale:$heightScale);
|
||||
}
|
||||
|
||||
noCacheHeaders();
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('CycleWatch') );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo $navbar = getNavBarHTML(); ?>
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<?php if ( $mode == "stream" ) { ?>
|
||||
<a href="?view=<?php echo $view ?>&mode=still&group=<?php echo $group ?>&mid=<?php echo $monitor->Id() ?>"><?php echo translate('Stills') ?></a>
|
||||
<a href="?view=<?php echo $view ?>&mode=still&mid=<?php echo $monitor ? $monitor->Id() : '' ?>"><?php echo translate('Stills') ?></a>
|
||||
<?php } else { ?>
|
||||
<a href="?view=<?php echo $view ?>&mode=stream&group=<?php echo $group ?>&mid=<?php echo $monitor->Id() ?>"><?php echo translate('Stream') ?></a>
|
||||
<a href="?view=<?php echo $view ?>&mode=stream&mid=<?php echo $monitor ? $monitor->Id() : '' ?>"><?php echo translate('Stream') ?></a>
|
||||
<?php } ?>
|
||||
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
|
||||
</div>
|
||||
<h2><?php echo translate('Cycle') ?> - <?php echo validHtmlStr($monitor->Name()) ?></h2>
|
||||
<div class="controlHeader">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
|
||||
$groups = array(0=>'All');
|
||||
foreach ( Group::find_all( array('ParentId'=>null) ) as $Group ) {
|
||||
$groups[$Group->Id()] = $Group->Name();
|
||||
}
|
||||
echo htmlSelect( 'group', $groups, $group_id, 'changeGroup(this);' );
|
||||
$groups = array(0=>'All');
|
||||
if ( $group_id ) {
|
||||
foreach ( Group::find_all( array('ParentId'=>$group_id) ) as $Group ) {
|
||||
$groups[$Group->Id()] = $Group->Name();
|
||||
}
|
||||
}
|
||||
echo htmlSelect( 'subgroup', $groups, $subgroup_id, 'changeSubGroup(this);' );
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="imageFeed">
|
||||
<?php echo getStreamHTML( $monitor, array( 'scale'=>$scale, 'mode'=>$mode ) ); ?>
|
||||
<?php
|
||||
if ( $monitor ) {
|
||||
echo getStreamHTML( $monitor, array( 'scale'=>$scale, 'mode'=>$mode ) );
|
||||
} else {
|
||||
echo "There are no monitors to view.";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -104,7 +104,7 @@ if ( ! $Event->Id() ) {
|
|||
} else {
|
||||
?>
|
||||
<div id="dataBar">
|
||||
<table id="dataTable" class="major" cellspacing="0">
|
||||
<table id="dataTable" class="major">
|
||||
<tr>
|
||||
<td><span id="dataId" title="<?php echo translate('Id') ?>"><?php echo $Event->Id() ?></span></td>
|
||||
<td><span id="dataCause" title="<?php echo $Event->Notes()?validHtmlStr($Event->Notes()):translate('AttrCause') ?>"><?php echo validHtmlStr($Event->Cause()) ?></span></td>
|
||||
|
@ -126,16 +126,16 @@ if ( ! $Event->Id() ) {
|
|||
<div id="menuBar2">
|
||||
<div id="closeWindow"><a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a></div>
|
||||
<?php
|
||||
if ( canEdit( 'Events' ) ) {
|
||||
if ( canEdit('Events') ) {
|
||||
?>
|
||||
<div id="deleteEvent"><a href="#" onclick="deleteEvent()"><?php echo translate('Delete') ?></a></div>
|
||||
<div id="editEvent"><a href="#" onclick="editEvent()"><?php echo translate('Edit') ?></a></div>
|
||||
<div id="archiveEvent" class="hidden"><a href="#" onclick="archiveEvent()"><?php echo translate('Archive') ?></a></div>
|
||||
<div id="unarchiveEvent" class="hidden"><a href="#" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></a></div>
|
||||
<div id="archiveEvent"<?php echo $Event->Archived == 1 ? ' class="hidden"' : '' ?>><a href="#" onclick="archiveEvent()"><?php echo translate('Archive') ?></a></div>
|
||||
<div id="unarchiveEvent"<?php echo $Event->Archived == 0 ? ' class="hidden"' : '' ?>><a href="#" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></a></div>
|
||||
<?php
|
||||
} // end if can edit Events
|
||||
if ( $Event->DefaultVideo() ) { ?>
|
||||
<div id="downloadEventFile"><a href="<?php echo $Event->getStreamSrc()?>">Download MP4</a></div>
|
||||
<div id="downloadEventFile"><a href="<?php echo $Event->getStreamSrc(array('mode'=>'mp4'))?>">Download MP4</a></div>
|
||||
<?php
|
||||
} // end if Event->DefaultVideo
|
||||
?>
|
||||
|
@ -167,12 +167,23 @@ if ( $Event->DefaultVideo() ) {
|
|||
var duration = <?php echo $Event->Length() ?>, startTime = '<?php echo $Event->StartTime() ?>';
|
||||
|
||||
addVideoTimingTrack(document.getElementById('videoobj'), LabelFormat, monitorName, duration, startTime);
|
||||
|
||||
nearEventsQuery( eventData.Id );
|
||||
vjsReplay(<?php echo (strtotime($Event->StartTime()) + $Event->Length())*1000 ?>);
|
||||
</script>
|
||||
|
||||
<p id="replayAllCountDown"></p>
|
||||
<p id="dvrControlsVjs" class="dvrControls">
|
||||
<input type="button" value="<+" id="prevBtnVjs" title="<?php echo translate('Prev') ?>" class="active" onclick="streamPrev( true );"/>
|
||||
<input type="button" value="+>" id="nextBtnVjs" title="<?php echo translate('Next') ?>" class="active" onclick="streamNext( true );"/>
|
||||
</p>
|
||||
|
||||
<?php
|
||||
} // end if DefaultVideo
|
||||
?>
|
||||
</div><!--eventVideo-->
|
||||
<div id="imageFeed"<?php if ( $Event->DefaultVideo() ) { ?> class="hidden"<?php } ?>>
|
||||
<?php if (!$Event->DefaultVideo()) { ?>
|
||||
<div id="imageFeed">
|
||||
<?php
|
||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
$streamSrc = $Event->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode ) );
|
||||
|
@ -186,7 +197,7 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
}
|
||||
} // end if stream method
|
||||
?>
|
||||
<p id="dvrControls">
|
||||
<p id="dvrControls" class="dvrControls">
|
||||
<input type="button" value="<+" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" onclick="streamPrev( true );"/>
|
||||
<input type="button" value="<<" id="fastRevBtn" title="<?php echo translate('Rewind') ?>" class="inactive" disabled="disabled" onclick="streamFastRev( true );"/>
|
||||
<input type="button" value="<" id="slowRevBtn" title="<?php echo translate('StepBack') ?>" class="unavail" disabled="disabled" onclick="streamSlowRev( true );"/>
|
||||
|
@ -210,6 +221,7 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
</div><!--progressBar-->
|
||||
</div><!--imageFeed-->
|
||||
</div>
|
||||
<?php } /*end if !DefaultVideo*/ ?>
|
||||
<?php
|
||||
if ( $Event->SaveJPEGs() & 3 ) { // frames or analysis
|
||||
?>
|
||||
|
@ -220,7 +232,7 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
</div>
|
||||
<div id="eventImagePanel">
|
||||
<div id="eventImageFrame">
|
||||
<img id="eventImage" src="graphics/transparent.gif" alt=""/>
|
||||
<img id="eventImage" src="graphics/transparent.png" alt=""/>
|
||||
<div id="eventImageBar">
|
||||
<div id="eventImageClose"><input type="button" value="<?php echo translate('Close') ?>" onclick="hideEventImage()"/></div>
|
||||
<div id="eventImageStats" class="hidden"><input type="button" value="<?php echo translate('Stats') ?>" onclick="showFrameStats()"/></div>
|
||||
|
|
|
@ -18,17 +18,12 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView( 'Events' ) )
|
||||
{
|
||||
$view = "error";
|
||||
return;
|
||||
if ( !canView( 'Events' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
# Must re-start session because we close it now in index.php to improve concurrency
|
||||
session_start();
|
||||
|
||||
if ( isset($_SESSION['export']) )
|
||||
{
|
||||
if ( isset($_SESSION['export']) ) {
|
||||
if ( isset($_SESSION['export']['detail']) )
|
||||
$_REQUEST['exportDetail'] = $_SESSION['export']['detail'];
|
||||
if ( isset($_SESSION['export']['frames']) )
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
//
|
||||
|
||||
if ( !canEdit( 'Monitors' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
$monitor = dbFetchMonitor( $_REQUEST['mid'] );
|
||||
|
|
|
@ -18,59 +18,101 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canEdit( 'Groups' ) )
|
||||
{
|
||||
$view = "error";
|
||||
return;
|
||||
if ( !canEdit( 'Groups' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !empty($_REQUEST['gid']) )
|
||||
{
|
||||
$newGroup = dbFetchGroup( $_REQUEST['gid'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$newGroup = array(
|
||||
"Id" => "",
|
||||
"Name" => "New Group",
|
||||
"MonitorIds" => ""
|
||||
);
|
||||
if ( !empty($_REQUEST['gid']) ) {
|
||||
$newGroup = new Group( $_REQUEST['gid'] );
|
||||
} else {
|
||||
$newGroup = new Group();
|
||||
}
|
||||
|
||||
xhtmlHeaders( __FILE__, translate('Group')." - ".$newGroup['Name'] );
|
||||
xhtmlHeaders( __FILE__, translate('Group').' - '.$newGroup->Name() );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="header">
|
||||
<h2><?php echo translate('Group') ?> - <?php echo $newGroup['Name'] ?></h2>
|
||||
<h2><?php echo translate('Group') ?> - <?php echo $newGroup->Name() ?></h2>
|
||||
</div>
|
||||
<div id="content">
|
||||
<form name="groupForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="action" value="group"/>
|
||||
<input type="hidden" name="gid" value="<?php echo $newGroup['Id'] ?>"/>
|
||||
<table id="contentTable" class="major" cellspacing="0">
|
||||
<input type="hidden" name="gid" value="<?php echo $newGroup->Id() ?>"/>
|
||||
<table id="contentTable" class="major">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Name') ?></th>
|
||||
<td><input type="text" name="newGroup[Name]" value="<?php echo validHtmlStr($newGroup['Name']) ?>"/></td>
|
||||
<td><input type="text" name="newGroup[Name]" value="<?php echo validHtmlStr($newGroup->Name()) ?>" oninput="configureButtons(this);"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('MonitorIds') ?></th>
|
||||
<th scope="row"><?php echo translate('ParentGroup') ?></th>
|
||||
<td>
|
||||
<select name="newGroup[MonitorIds][]" size="4" multiple="multiple">
|
||||
<?php
|
||||
$monitors = dbFetchAll( "select Id,Name from Monitors order by Sequence asc" );
|
||||
$monitorIds = array_flip( explode( ',', $newGroup['MonitorIds'] ) );
|
||||
foreach ( $monitors as $monitor )
|
||||
{
|
||||
if ( visibleMonitor( $monitor['Id'] ) )
|
||||
{
|
||||
?>
|
||||
<option value="<?php echo $monitor['Id'] ?>"<?php if ( array_key_exists( $monitor['Id'], $monitorIds ) ) { ?> selected="selected"<?php } ?> onclick="configureButtons( this );"><?php echo validHtmlStr($monitor['Name']) ?></option>
|
||||
<?php
|
||||
}
|
||||
$Groups = array();
|
||||
foreach ( Group::find_all( ) as $Group ) {
|
||||
$Groups[$Group->Id()] = $Group;
|
||||
}
|
||||
|
||||
# This array is indexed by parent_id
|
||||
$children = array();
|
||||
|
||||
foreach ( $Groups as $id=>$Group ) {
|
||||
if ( $Group->ParentId() != null ) {
|
||||
if ( ! isset( $children[$Group->ParentId()] ) )
|
||||
$children[$Group->ParentId()] = array();
|
||||
$children[$Group->ParentId()][] = $Group;
|
||||
}
|
||||
}
|
||||
|
||||
function get_Id( $G ) {
|
||||
return $G->Id();
|
||||
}
|
||||
|
||||
function get_children($Group) {
|
||||
global $children;
|
||||
|
||||
$kids = array();
|
||||
if ( isset( $children[$Group->Id()] ) ) {
|
||||
$kids += array_map( 'get_Id', $children[$Group->Id()] );
|
||||
foreach ( $children[$Group->Id()] as $G ) {
|
||||
foreach ( get_children($G) as $id ) {
|
||||
$kids[] = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $kids;
|
||||
}
|
||||
|
||||
$kids = get_children($newGroup);
|
||||
$kids[] = $newGroup->Id();
|
||||
function get_question_marks() {
|
||||
return '?';
|
||||
}
|
||||
$options = array(''=>'None');
|
||||
foreach ( dbFetchAll( 'SELECT Id,Name from Groups WHERE Id NOT IN ('.implode(',',array_map('get_question_marks', $kids )).') ORDER BY Name', null, $kids ) as $option ) {
|
||||
$options[$option['Id']] = $option['Name'];
|
||||
}
|
||||
echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' ));
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Monitor') ?></th>
|
||||
<td>
|
||||
<select name="newGroup[MonitorIds][]" size="4" multiple="multiple" onchange="configureButtons(this);">
|
||||
<?php
|
||||
$monitors = dbFetchAll( 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC' );
|
||||
$monitorIds = array_flip( explode( ',', $newGroup->MonitorIds() ) );
|
||||
foreach ( $monitors as $monitor ) {
|
||||
if ( visibleMonitor( $monitor['Id'] ) ) {
|
||||
?>
|
||||
<option value="<?php echo $monitor['Id'] ?>"<?php if ( array_key_exists( $monitor['Id'], $monitorIds ) ) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($monitor['Name']) ?></option>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</td>
|
||||
|
@ -78,7 +120,7 @@ xhtmlHeaders( __FILE__, translate('Group')." - ".$newGroup['Name'] );
|
|||
</tbody>
|
||||
</table>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" name="saveBtn" value="<?php echo translate('Save') ?>" disabled="disabled" />
|
||||
<input type="submit" name="saveBtn" value="<?php echo translate('Save') ?>"<?php $newGroup->Id() ? '' : ' disabled="disabled"'?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -19,67 +19,80 @@
|
|||
//
|
||||
|
||||
if ( !canView( 'Groups' ) ) {
|
||||
$view = "error";
|
||||
return;
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = "select * from Groups order by Name";
|
||||
$groups = array();
|
||||
$selected = false;
|
||||
foreach( dbFetchAll( $sql ) as $row )
|
||||
{
|
||||
if ( !empty($_COOKIE['zmGroup']) && ($row['Id'] == $_COOKIE['zmGroup']) )
|
||||
{
|
||||
$row['selected'] = true;
|
||||
$selected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$row['selected'] = false;
|
||||
}
|
||||
$groups[] = $row;
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = 0;
|
||||
$max_depth = 0;
|
||||
|
||||
|
||||
$Groups = array();
|
||||
foreach ( Group::find_all( ) as $Group ) {
|
||||
$Groups[$Group->Id()] = $Group;
|
||||
}
|
||||
|
||||
# This array is indexed by parent_id
|
||||
$children = array();
|
||||
foreach ( $Groups as $id=>$Group ) {
|
||||
if ( ! isset( $children[$Group->ParentId()] ) )
|
||||
$children[$Group->ParentId()] = array();
|
||||
$children[$Group->ParentId()][] = $Group;
|
||||
if ( $max_depth < $Group->depth() )
|
||||
$max_depth = $Group->depth();
|
||||
}
|
||||
Warning("Max depth $max_depth");
|
||||
xhtmlHeaders(__FILE__, translate('Groups') );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="header">
|
||||
<h2><?php echo translate('Groups') ?></h2>
|
||||
</div>
|
||||
<?php echo $navbar = getNavBarHTML(); ?>
|
||||
<div id="content">
|
||||
<form name="groupsForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="none"/>
|
||||
<input type="hidden" name="action" value="setgroup"/>
|
||||
<table id="contentTable" class="major" cellspacing="0">
|
||||
<table id="contentTable" class="major">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="colName"><?php echo translate('Name') ?></th>
|
||||
<th class="colIds"><?php echo translate('MonitorIds') ?></th>
|
||||
<th class="colSelect"><?php echo translate('Select') ?></th>
|
||||
<th class="colName" colspan="<?php echo $max_depth ?>"><?php echo translate('Name') ?></th>
|
||||
<th class="colIds"><?php echo translate('Monitors') ?></th>
|
||||
<th class="colSelect"><?php echo translate('Mark') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="highlight">
|
||||
<td class="colName"><?php echo translate('NoGroup') ?></td>
|
||||
<td class="colIds"><?php echo translate('All') ?></td>
|
||||
<td class="colSelect"><input type="radio" name="gid" value="0"<?php echo !$selected?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
|
||||
</tr>
|
||||
<?php foreach ( $groups as $group ) { ?>
|
||||
<tr>
|
||||
<td class="colName"><?php echo validHtmlStr($group['Name']) ?></td>
|
||||
<td class="colIds"><?php echo monitorIdsToNames( $group['MonitorIds'], 30 ) ?></td>
|
||||
<td class="colSelect"><input type="radio" name="gid" value="<?php echo $group['Id'] ?>"<?php echo $group['selected']?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<?php
|
||||
function group_line( $Group ) {
|
||||
global $children;
|
||||
global $max_depth;
|
||||
$html = '<tr>';
|
||||
for ( $i = 1; $i<$Group->depth(); $i+=1 )
|
||||
$html .= '<td class="colName"> </td>';
|
||||
$html .= '<td class="colName" colspan="'.($max_depth-($Group->depth()-1)).'">';
|
||||
if ( canEdit('Groups') ) {
|
||||
$html .= '<a href="#" onclick="editGroup('.$Group->Id().');">'. validHtmlStr($Group->Name()).'</a>';
|
||||
} else {
|
||||
$html .= validHtmlStr($Group->Name());
|
||||
}
|
||||
$html .= '</td><td class="colIds">'. monitorIdsToNames( $Group->MonitorIds(), 30 ).'</td>
|
||||
<td class="colSelect"><input type="checkbox" name="gid" value="'. $Group->Id() .'" onclick="configureButtons(this);"/></td>
|
||||
</tr>
|
||||
';
|
||||
if ( isset( $children[$Group->Id()] ) ) {
|
||||
foreach ( $children[$Group->Id()] as $G ) {
|
||||
$html .= group_line( $G );
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
foreach ( $children[null] as $Group )
|
||||
echo group_line( $Group );
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" value="<?php echo translate('Apply') ?>"/>
|
||||
<input type="button" value="<?php echo translate('New') ?>" onclick="newGroup()"<?php echo canEdit('Groups')?'':' disabled="disabled"' ?>/>
|
||||
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editGroup( this )"<?php echo $selected&&canEdit('Groups')?'':' disabled="disabled"' ?>/>
|
||||
<input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteGroup( this )"<?php echo $selected&&canEdit('Groups')?'':' disabled="disabled"' ?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow();"/>
|
||||
<input type="button" value="<?php echo translate('New') ?>" onclick="newGroup();"<?php echo canEdit('Groups')?'':' disabled="disabled"' ?>/>
|
||||
<input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteGroup(this);" disabled="disabled"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
function nextCycleView() {
|
||||
window.location.replace( '?view=cycle&group='+currGroup+'&mid='+nextMid+'&mode='+mode, cycleRefreshTimeout );
|
||||
window.location.replace( '?view=cycle&mid='+nextMid+'&mode='+mode, cycleRefreshTimeout );
|
||||
}
|
||||
|
||||
function initCycle() {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
var currGroup = "<?php echo isset($_REQUEST['group'])?validJsStr($_REQUEST['group']):'' ?>";
|
||||
var nextMid = "<?php echo isset($nextMid)?$nextMid:'' ?>";
|
||||
var mode = "<?php echo $mode ?>";
|
||||
|
||||
|
|
|
@ -1,5 +1,36 @@
|
|||
var vid = null;
|
||||
|
||||
function vjsReplay(endTime) {
|
||||
var video = videojs('videoobj').ready(function(){
|
||||
var player = this;
|
||||
player.on('ended', function() {
|
||||
switch(replayMode.value) {
|
||||
case 'none':
|
||||
break;
|
||||
case 'single':
|
||||
player.play();
|
||||
break;
|
||||
case 'all':
|
||||
// nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse
|
||||
var gapDuration = (new Date().getTime()) + (nextEventStartTime.getTime() - endTime);
|
||||
var x = setInterval(function() {
|
||||
var now = new Date().getTime();
|
||||
var remainder = new Date(Math.round(gapDuration - now)).toISOString().substr(11,8);;
|
||||
$j("#replayAllCountDown").html(remainder + " to next event.");
|
||||
if (remainder < 0) {
|
||||
clearInterval(x);
|
||||
streamNext( true );
|
||||
}
|
||||
}, 1000);
|
||||
break;
|
||||
case 'gapless':
|
||||
streamNext( true );
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setButtonState( element, butClass ) {
|
||||
if ( element ) {
|
||||
element.className = butClass;
|
||||
|
@ -164,13 +195,23 @@ function streamFastRev( action ) {
|
|||
}
|
||||
|
||||
function streamPrev( action ) {
|
||||
if ( action )
|
||||
if ( action ) {
|
||||
if ( vid ) {
|
||||
location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery);
|
||||
return;
|
||||
}
|
||||
streamReq.send( streamParms+"&command="+CMD_PREV );
|
||||
}
|
||||
}
|
||||
|
||||
function streamNext( action ) {
|
||||
if ( action )
|
||||
if ( action ) {
|
||||
if ( vid ) {
|
||||
location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery);
|
||||
return;
|
||||
}
|
||||
streamReq.send( streamParms+"&command="+CMD_NEXT );
|
||||
}
|
||||
}
|
||||
|
||||
function streamZoomIn( x, y ) {
|
||||
|
@ -251,6 +292,8 @@ function eventQuery( eventId ) {
|
|||
|
||||
var prevEventId = 0;
|
||||
var nextEventId = 0;
|
||||
var prevEventStartTime = 0;
|
||||
var nextEventStartTime = 0;
|
||||
var PrevEventDefVideoPath = "";
|
||||
var NextEventDefVideoPath = "";
|
||||
|
||||
|
@ -259,6 +302,8 @@ function getNearEventsResponse( respObj, respText ) {
|
|||
return;
|
||||
prevEventId = respObj.nearevents.PrevEventId;
|
||||
nextEventId = respObj.nearevents.NextEventId;
|
||||
prevEventStartTime = Date.parse(respObj.nearevents.PrevEventStartTime);
|
||||
nextEventStartTime = Date.parse(respObj.nearevents.NextEventStartTime);
|
||||
PrevEventDefVideoPath = respObj.nearevents.PrevEventDefVideoPath;
|
||||
NextEventDefVideoPath = respObj.nearevents.NextEventDefVideoPath;
|
||||
|
||||
|
@ -266,12 +311,14 @@ function getNearEventsResponse( respObj, respText ) {
|
|||
if ( prevEventBtn ) prevEventBtn.disabled = !prevEventId;
|
||||
var nextEventBtn = $('nextEventBtn');
|
||||
if ( nextEventBtn ) nextEventBtn.disabled = !nextEventId;
|
||||
if (prevEventId == 0) $j('#prevBtnVjs').prop('disabled', true).attr('class', 'unavail');
|
||||
if (nextEventId == 0) $j('#nextBtnVjs').prop('disabled', true).attr('class', 'unavail');
|
||||
}
|
||||
|
||||
var nearEventsReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getNearEventsResponse } );
|
||||
|
||||
function nearEventsQuery( eventId ) {
|
||||
var parms = "view=request&request=status&entity=nearevents&id="+eventId;
|
||||
var parms = "view=request&request=status&entity=nearevents&id="+eventId+filterQuery+sortQuery;
|
||||
nearEventsReq.send( parms );
|
||||
}
|
||||
|
||||
|
@ -455,7 +502,7 @@ function checkFrames( eventId, frameId, loadImage ) {
|
|||
|
||||
for ( var fid = loFid; fid <= hiFid; fid++ ) {
|
||||
if ( !$('eventThumb'+fid) ) {
|
||||
var img = new Element( 'img', { 'id': 'eventThumb'+fid, 'src': 'graphics/transparent.gif', 'alt': fid, 'class': 'placeholder' } );
|
||||
var img = new Element( 'img', { 'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder' } );
|
||||
img.addEvent( 'click', function() { eventData['frames'][fid] = null; checkFrames( eventId, fid ); } );
|
||||
frameQuery( eventId, fid, loadImage && (fid == frameId) );
|
||||
var imgs = $('eventThumbs').getElements( 'img' );
|
||||
|
|
|
@ -33,8 +33,8 @@ var eventData = {
|
|||
Length: '<?php echo $Event->Length() ?>'
|
||||
};
|
||||
|
||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr($filterQuery):'' ?>';
|
||||
var sortQuery = '<?php echo isset($sortQuery)?validJsStr($sortQuery):'' ?>';
|
||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
||||
var sortQuery = '<?php echo isset($sortQuery)?validJsStr(htmlspecialchars_decode($sortQuery)):'' ?>';
|
||||
|
||||
var scale = <?php echo $scale ?>;
|
||||
var canEditEvents = <?php echo canEdit( 'Events' )?'true':'false' ?>;
|
||||
|
|
|
@ -9,7 +9,12 @@ if ( refreshParent ) {
|
|||
function configureButtons( element ) {
|
||||
if ( canEditGroups ) {
|
||||
var form = element.form;
|
||||
form.saveBtn.disabled = (element.value == 0);
|
||||
var disabled = false;
|
||||
|
||||
if ( form.elements['newGroup[Name]'].value == '' ) {
|
||||
disabled = true;
|
||||
}
|
||||
form.saveBtn.disabled = disabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,20 +2,14 @@ function newGroup() {
|
|||
createPopup( '?view=group', 'zmGroup', 'group' );
|
||||
}
|
||||
|
||||
function editGroup( element ) {
|
||||
function setGroup( element ) {
|
||||
var form = element.form;
|
||||
form.action.value = 'setgroup';
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function editGroup( element ) {
|
||||
var form = element.form;
|
||||
for ( var i = 0; i < form.gid.length; i++ ) {
|
||||
if ( form.gid[i].checked ) {
|
||||
createPopup( '?view=group&gid='+form.gid[i].value, 'zmGroup', 'group' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
function editGroup( gid ) {
|
||||
createPopup( '?view=group&gid='+gid, 'zmGroup', 'group' );
|
||||
}
|
||||
|
||||
function deleteGroup( element ) {
|
||||
|
@ -29,7 +23,6 @@ function configureButtons( element ) {
|
|||
if ( canEditGroups ) {
|
||||
var form = element.form;
|
||||
if ( element.checked ) {
|
||||
form.editBtn.disabled = (element.value == 0);
|
||||
form.deleteBtn.disabled = (element.value == 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,6 @@ function changeSize() {
|
|||
src = src.replace(/height=[\.\d]+/i,'height='+height );
|
||||
src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
streamImg.src = src;
|
||||
|
||||
}
|
||||
streamImg.style.width = width? width + "px" : null;
|
||||
streamImg.style.height = height ? height + "px" : null;
|
||||
|
@ -210,7 +209,6 @@ function changeScale() {
|
|||
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } );
|
||||
}
|
||||
|
||||
|
||||
var monitors = new Array();
|
||||
function initPage() {
|
||||
for ( var i = 0; i < monitorData.length; i++ ) {
|
||||
|
|
|
@ -166,13 +166,12 @@ function drawSliderOnGraph(val) {
|
|||
|
||||
// If we have data already saved first restore it from LAST time
|
||||
|
||||
if(typeof underSlider !== 'undefined')
|
||||
{
|
||||
if(typeof underSlider !== 'undefined') {
|
||||
ctx.putImageData(underSlider,underSliderX, 0, 0, 0, sliderWidth, sliderHeight);
|
||||
underSlider=undefined;
|
||||
}
|
||||
if(liveMode==0) // we get rid of the slider if we switch to live (since it may not be in the "right" place)
|
||||
{
|
||||
if ( liveMode == 0 ) {
|
||||
// we get rid of the slider if we switch to live (since it may not be in the "right" place)
|
||||
// Now save where we are putting it THIS time
|
||||
underSlider=ctx.getImageData(sliderX, 0, sliderWidth, sliderHeight);
|
||||
// And add in the slider'
|
||||
|
@ -183,13 +182,10 @@ function drawSliderOnGraph(val) {
|
|||
underSliderX=sliderX;
|
||||
}
|
||||
var o = $('scruboutput');
|
||||
if(liveMode==1)
|
||||
{
|
||||
if(liveMode==1) {
|
||||
o.innerHTML="Live Feed @ " + (1000 / currentDisplayInterval).toFixed(1) + " fps";
|
||||
o.style.color="red";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
o.innerHTML=secs2dbstr(val);
|
||||
o.style.color="blue";
|
||||
}
|
||||
|
@ -293,16 +289,10 @@ function drawGraph()
|
|||
return;
|
||||
}
|
||||
|
||||
function redrawScreen()
|
||||
{
|
||||
if(fitMode==0) // if we fit, then monitors were absolutely positioned already (or will be) otherwise release them to float
|
||||
{
|
||||
for(var i=0; i<numMonitors; i++)
|
||||
monitorCanvasObj[monitorPtr[i]].style.position="";
|
||||
$('monitors').setStyle('height',"auto");
|
||||
}
|
||||
if(liveMode==1) // if we are not in live view switch to history -- this has to come before fit in case we re-establish the timeline
|
||||
{
|
||||
function redrawScreen() {
|
||||
if ( liveMode == 1 ) {
|
||||
// if we are not in live view switch to history -- this has to come before fit in case we re-establish the timeline
|
||||
$('DateTimeDiv').style.display="none";
|
||||
$('SpeedDiv').style.display="none";
|
||||
$('timelinediv').style.display="none";
|
||||
$('live').innerHTML="History";
|
||||
|
@ -311,9 +301,9 @@ function redrawScreen()
|
|||
$('panleft').style.display="none";
|
||||
$('panright').style.display="none";
|
||||
|
||||
}
|
||||
else // switch out of liveview mode
|
||||
{
|
||||
} else {
|
||||
// switch out of liveview mode
|
||||
$('DateTimeDiv').style.display="inline";
|
||||
$('SpeedDiv').style.display="inline";
|
||||
$('SpeedDiv').style.display="inline-flex";
|
||||
$('timelinediv').style.display=null;
|
||||
|
@ -328,8 +318,7 @@ function redrawScreen()
|
|||
$('panright').style.display="inline-flex";
|
||||
}
|
||||
|
||||
if(fitMode==1)
|
||||
{
|
||||
if ( fitMode == 1 ) {
|
||||
$('ScaleDiv').style.display="none";
|
||||
$('fit').innerHTML="Scale";
|
||||
var vh=window.innerHeight;
|
||||
|
@ -339,9 +328,12 @@ function redrawScreen()
|
|||
$('monitors').setStyle('height',mh.toString() + "px"); // leave a small gap at bottom
|
||||
if(maxfit2($('monitors').getSize().x,$('monitors').getSize().y) == 0) /// if we fail to fix we back out of fit mode -- ??? This may need some better handling
|
||||
fitMode=1-fitMode;
|
||||
}
|
||||
else // switch out of fit mode
|
||||
{
|
||||
} else {
|
||||
// switch out of fit mode
|
||||
// if we fit, then monitors were absolutely positioned already (or will be) otherwise release them to float
|
||||
for( var i=0; i<numMonitors; i++ )
|
||||
monitorCanvasObj[monitorPtr[i]].style.position="";
|
||||
$('monitors').setStyle('height',"auto");
|
||||
$('ScaleDiv').style.display="inline";
|
||||
$('ScaleDiv').style.display="inline-flex";
|
||||
$('fit').innerHTML="Fit";
|
||||
|
@ -353,15 +345,13 @@ function redrawScreen()
|
|||
}
|
||||
|
||||
|
||||
function outputUpdate(val)
|
||||
{
|
||||
drawSliderOnGraph(val);
|
||||
for(var i=0; i<numMonitors; i++)
|
||||
{
|
||||
loadImage2Monitor(monitorPtr[i],SetImageSource(monitorPtr[i],val));
|
||||
}
|
||||
var currentTimeMS = new Date(val*1000);
|
||||
currentTimeSecs=val;
|
||||
function outputUpdate(val) {
|
||||
drawSliderOnGraph(val);
|
||||
for(var i=0; i<numMonitors; i++) {
|
||||
loadImage2Monitor(monitorPtr[i],SetImageSource(monitorPtr[i],val));
|
||||
}
|
||||
var currentTimeMS = new Date(val*1000);
|
||||
currentTimeSecs=val;
|
||||
}
|
||||
|
||||
|
||||
|
@ -402,16 +392,18 @@ function mmove(event) {
|
|||
}
|
||||
}
|
||||
|
||||
function secs2dbstr (s)
|
||||
{
|
||||
var st = (new Date(s * 1000)).format("%Y-%m-%d %H:%M:%S");
|
||||
return st;
|
||||
function secs2inputstr (s) {
|
||||
var st = (new Date(s * 1000)).format("%Y-%m-%dT%H:%M:%S");
|
||||
return st;
|
||||
}
|
||||
function secs2dbstr (s) {
|
||||
var st = (new Date(s * 1000)).format("%Y-%m-%d %H:%M:%S");
|
||||
return st;
|
||||
}
|
||||
|
||||
function setFit(value)
|
||||
{
|
||||
fitMode=value;
|
||||
redrawScreen();
|
||||
function setFit(value) {
|
||||
fitMode=value;
|
||||
redrawScreen();
|
||||
}
|
||||
|
||||
function showScale(newscale) // updates slider only
|
||||
|
@ -431,13 +423,12 @@ function setScale(newscale) // makes actual change
|
|||
currentScale=newscale;
|
||||
}
|
||||
|
||||
function showSpeed(val) // updates slider only
|
||||
{
|
||||
$('speedslideroutput').innerHTML = parseFloat(speeds[val]).toFixed(2).toString() + " x";
|
||||
function showSpeed(val) {
|
||||
// updates slider only
|
||||
$('speedslideroutput').innerHTML = parseFloat(speeds[val]).toFixed(2).toString() + " x";
|
||||
}
|
||||
|
||||
function setSpeed(val) // Note parameter is the index not the speed
|
||||
{
|
||||
function setSpeed(val) { // Note parameter is the index not the speed
|
||||
var t;
|
||||
if(liveMode==1) return; // we shouldn't actually get here but just in case
|
||||
currentSpeed=parseFloat(speeds[val]);
|
||||
|
@ -447,8 +438,7 @@ function setSpeed(val) // Note parameter is the index not the speed
|
|||
if( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update
|
||||
}
|
||||
|
||||
function setLive(value)
|
||||
{
|
||||
function setLive(value) {
|
||||
liveMode=value;
|
||||
redrawScreen();
|
||||
}
|
||||
|
@ -459,19 +449,22 @@ function setLive(value)
|
|||
|
||||
function clicknav(minSecs,maxSecs,arch,live) {// we use the current time if we can
|
||||
var now = new Date() / 1000;
|
||||
var minStr="";
|
||||
var maxStr="";
|
||||
var currentStr="";
|
||||
var minStr = "";
|
||||
var maxStr = "";
|
||||
var currentStr = "";
|
||||
if ( minSecs > 0 ) {
|
||||
if(maxSecs > now)
|
||||
maxSecs = parseInt(now);
|
||||
maxStr="&maxTime=" + secs2dbstr(maxSecs);
|
||||
maxStr="&maxTime=" + secs2inputstr(maxSecs);
|
||||
$('maxTime').value = secs2inputstr(maxSecs);
|
||||
}
|
||||
if ( minSecs > 0 ) {
|
||||
$('minTime').value = secs2inputstr(minSecs);
|
||||
minStr="&minTime=" + secs2inputstr(minSecs);
|
||||
}
|
||||
if ( maxSecs > 0 )
|
||||
minStr="&minTime=" + secs2dbstr(minSecs);
|
||||
if ( maxSecs == 0 && minSecs == 0 ) {
|
||||
minStr="&minTime=01/01/1950 12:00:00";
|
||||
maxStr="&maxTime=12/31/2035 12:00:00";
|
||||
minStr="&minTime=01/01/1950T12:00:00";
|
||||
maxStr="&maxTime=12/31/2035T12:00:00";
|
||||
}
|
||||
var intervalStr="&displayinterval=" + currentDisplayInterval.toString();
|
||||
if ( minSecs && maxSecs ) {
|
||||
|
@ -492,42 +485,42 @@ function clicknav(minSecs,maxSecs,arch,live) {// we use the current time if we c
|
|||
if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1
|
||||
zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2);
|
||||
|
||||
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + document.getElementById("scaleslider").value + "&speed=" + speeds[$j("#speedslider").value];
|
||||
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
|
||||
window.location = uri;
|
||||
}
|
||||
} // end function clickNav
|
||||
|
||||
function lastHour() {
|
||||
function click_lastHour() {
|
||||
var now = new Date() / 1000;
|
||||
clicknav(now - 3600 + 1, now,1,0);
|
||||
}
|
||||
function lastEight() {
|
||||
function click_lastEight() {
|
||||
var now = new Date() / 1000;
|
||||
clicknav(now - 3600*8 + 1, now,1,0);
|
||||
}
|
||||
function zoomin() {
|
||||
function click_zoomin() {
|
||||
rangeTimeSecs = parseInt(rangeTimeSecs / 2);
|
||||
minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that
|
||||
maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2);
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
|
||||
function zoomout() {
|
||||
function click_zoomout() {
|
||||
rangeTimeSecs = parseInt(rangeTimeSecs * 2);
|
||||
minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that
|
||||
maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2);
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function panleft() {
|
||||
function click_panleft() {
|
||||
minTimeSecs = parseInt(minTimeSecs - rangeTimeSecs/2);
|
||||
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function panright() {
|
||||
function click_panright() {
|
||||
minTimeSecs = parseInt(minTimeSecs + rangeTimeSecs/2);
|
||||
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function allof() {
|
||||
function click_all_events() {
|
||||
clicknav(0,0,1,0);
|
||||
}
|
||||
function allnon() {
|
||||
|
@ -690,6 +683,10 @@ function clickMonitor(event,monId) {
|
|||
return;
|
||||
}
|
||||
|
||||
function changeDateTime(e) {
|
||||
e.form.submit();
|
||||
}
|
||||
|
||||
// >>>>>>>>> Initialization that runs on window load by being at the bottom
|
||||
|
||||
function initPage() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
var currentScale=<?php echo $defaultScale?>;
|
||||
var liveMode=<?php echo $initialModeIsLive?>;
|
||||
console.log("Live mode?"+liveMode);
|
||||
var fitMode=<?php echo $fitMode?>;
|
||||
var currentSpeed=<?php echo $speeds[$speedIndex]?>; // slider scale, which is only for replay and relative to real time
|
||||
var speedIndex=<?php echo $speedIndex?>;
|
||||
|
@ -18,7 +17,7 @@ var eId = [];
|
|||
var eStartSecs = [];
|
||||
var eEndSecs = [];
|
||||
var eventFrames = []; // this is going to presume all frames equal durationlength
|
||||
var groupStr=<?php if($group=="") echo '""'; else echo "\"&group=$group\""; ?>;
|
||||
var groupStr=<?php echo $group_id ? "'&group=$group_id'" : '""'; ?>;
|
||||
|
||||
<?php
|
||||
|
||||
|
@ -178,8 +177,8 @@ foreach ( $monitors as $m ) {
|
|||
$numMonitors += 1;
|
||||
}
|
||||
echo "var numMonitors = $numMonitors;\n";
|
||||
echo "var minTimeSecs=" . $minTimeSecs . ";\n";
|
||||
echo "var maxTimeSecs=" . $maxTimeSecs . ";\n";
|
||||
echo "var minTimeSecs='" . $minTimeSecs . "';\n";
|
||||
echo "var maxTimeSecs='" . $maxTimeSecs . "';\n";
|
||||
echo "var rangeTimeSecs=" . ( $maxTimeSecs - $minTimeSecs + 1) . ";\n";
|
||||
if(isset($defaultCurrentTime))
|
||||
echo "var currentTimeSecs=" . strtotime($defaultCurrentTime) . ";\n";
|
||||
|
|
|
@ -31,7 +31,6 @@ $j(document).ready(function() {
|
|||
// Save a new state
|
||||
$j("#btnSave").click(function() {
|
||||
StateStuff( 'save', undefined, $j("#newState").val() );
|
||||
|
||||
});
|
||||
|
||||
// Change state
|
||||
|
@ -53,7 +52,7 @@ $j(document).ready(function() {
|
|||
|
||||
$j.ajax({
|
||||
type: 'POST',
|
||||
url: '/index.php',
|
||||
url: thisUrl,
|
||||
data: formData,
|
||||
dataType: 'html',
|
||||
enocde: true
|
||||
|
|
|
@ -94,7 +94,7 @@ function previewEvent( eventId, frameId ) {
|
|||
if ( event['frames'] ) {
|
||||
if ( event['frames'][frameId] ) {
|
||||
showEventDetail( event['frames'][frameId]['html'] );
|
||||
var imagePath = '/index.php?view=image&eid='+eventId+'&fid='+frameId;
|
||||
var imagePath = 'index.php?view=image&eid='+eventId+'&fid='+frameId;
|
||||
var videoName = event.DefaultVideo;
|
||||
loadEventImage( imagePath, eventId, frameId, event.Width, event.Height, event.Frames/event.Length, videoName, event.Length, event.StartTime, monitors[event.MonitorId]);
|
||||
return;
|
||||
|
|
|
@ -496,16 +496,20 @@ function getStreamCmdResponse( respObj, respText ) {
|
|||
}
|
||||
} else {
|
||||
checkStreamForErrors("getStreamCmdResponse", respObj);//log them
|
||||
// Try to reload the image stream.
|
||||
var streamImg = document.getElementById('liveStream');
|
||||
if ( streamImg )
|
||||
streamImg.src = streamImg.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
if ( ! streamPause ) {
|
||||
// Try to reload the image stream.
|
||||
var streamImg = $('liveStream'+monitorId);
|
||||
if ( streamImg )
|
||||
streamImg.src = streamImg.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
}
|
||||
}
|
||||
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
streamCmdTimer = streamCmdQuery.delay( streamCmdTimeout );
|
||||
if ( ! streamPause ) {
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
streamCmdTimer = streamCmdQuery.delay( streamCmdTimeout );
|
||||
}
|
||||
}
|
||||
|
||||
var streamPause = false;
|
||||
|
@ -556,10 +560,12 @@ function getStatusCmdResponse( respObj, respText ) {
|
|||
} else
|
||||
checkStreamForErrors("getStatusCmdResponse", respObj);
|
||||
|
||||
var statusCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
|
||||
statusCmdTimeout = statusCmdTimeout/5;
|
||||
statusCmdTimer = statusCmdQuery.delay( statusCmdTimeout );
|
||||
if ( ! streamPause ) {
|
||||
var statusCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
|
||||
statusCmdTimeout = statusCmdTimeout/5;
|
||||
statusCmdTimer = statusCmdQuery.delay( statusCmdTimeout );
|
||||
}
|
||||
}
|
||||
|
||||
function statusCmdQuery() {
|
||||
|
|
|
@ -2,7 +2,7 @@ var streamCmdParms = "view=request&request=stream&connkey="+connKey;
|
|||
var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel' } );
|
||||
|
||||
function streamCmdQuit( action ) {
|
||||
if ( action )
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUIT );
|
||||
if ( action )
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUIT );
|
||||
}
|
||||
|
||||
|
|
|
@ -51,11 +51,13 @@ if ( ! $Server ) {
|
|||
$Server = array( 'Id' => '' );
|
||||
}
|
||||
|
||||
$monitor = null;
|
||||
if ( ! empty($_REQUEST['mid']) ) {
|
||||
$monitor = new Monitor( $_REQUEST['mid'] );
|
||||
if ( ZM_OPT_X10 )
|
||||
if ( $monitor and ZM_OPT_X10 )
|
||||
$x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid']) );
|
||||
} else {
|
||||
}
|
||||
if ( ! $monitor ) {
|
||||
|
||||
$nextId = getTableAutoInc( 'Monitors' );
|
||||
if ( isset( $_REQUEST['dupId'] ) ) {
|
||||
|
@ -207,7 +209,8 @@ $sourceTypes = array(
|
|||
'File' => translate('File'),
|
||||
'Ffmpeg' => translate('Ffmpeg'),
|
||||
'Libvlc' => translate('Libvlc'),
|
||||
'cURL' => 'cURL (HTTP(S) only)'
|
||||
'cURL' => 'cURL (HTTP(S) only)',
|
||||
'NVSocket' => translate('NVSocket')
|
||||
);
|
||||
if ( !ZM_HAS_V4L )
|
||||
unset($sourceTypes['Local']);
|
||||
|
@ -395,12 +398,12 @@ $Colours = array(
|
|||
);
|
||||
|
||||
$orientations = array(
|
||||
translate('Normal') => '0',
|
||||
translate('RotateRight') => '90',
|
||||
translate('Inverted') => '180',
|
||||
translate('RotateLeft') => '270',
|
||||
translate('FlippedHori') => 'hori',
|
||||
translate('FlippedVert') => 'vert'
|
||||
'0' => translate('Normal'),
|
||||
'90' => translate('RotateRight'),
|
||||
'180' => translate('Inverted'),
|
||||
'270' => translate('RotateLeft'),
|
||||
'horz' => translate('FlippedHori'),
|
||||
'vert' => translate('FlippedVert')
|
||||
);
|
||||
|
||||
$deinterlaceopts = array(
|
||||
|
@ -498,7 +501,7 @@ if ( canEdit( 'Monitors' ) ) {
|
|||
<?php
|
||||
} // end if canEdit('Monitors')
|
||||
?>
|
||||
<h2><?php echo translate('Monitor') ?> - <?php echo validHtmlStr($monitor->Name()) ?><?php if ( !empty($monitor->Id()) ) { ?> (<?php echo $monitor->Id()?>)<?php } ?></h2>
|
||||
<h2><?php echo translate('Monitor') ?> - <?php echo validHtmlStr($monitor->Name()) ?><?php if ( $monitor->Id() ) { ?> (<?php echo $monitor->Id()?>)<?php } ?></h2>
|
||||
</div>
|
||||
<div id="content">
|
||||
<ul class="tabList">
|
||||
|
@ -598,7 +601,7 @@ if ( $tab != 'storage' ) {
|
|||
<input type="hidden" name="newMonitor[RecordAudio]" value="<?php echo validHtmlStr($monitor->RecordAudio()) ?>"/>
|
||||
<?php
|
||||
}
|
||||
if ( $tab != 'source' || ($monitor->Type()!= 'Remote' && $monitor->Protocol()!= 'rtsp') ) {
|
||||
if ( $tab != 'source' || ($monitor->Type() != 'Remote' && $monitor->Protocol()!= 'rtsp') ) {
|
||||
?>
|
||||
<input type="hidden" name="newMonitor[RTSPDescribe]" value="<?php echo validHtmlStr($monitor->RTSPDescribe()) ?>"/>
|
||||
<?php
|
||||
|
@ -702,19 +705,19 @@ switch ( $tab ) {
|
|||
}
|
||||
?>
|
||||
</select></td></tr>
|
||||
<tr><td><?php echo translate('Enabled') ?></td><td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php if ( !empty($monitor->Enabled()) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('Enabled') ?></td><td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php if ( $monitor->Enabled() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('LinkedMonitors') ?></td>
|
||||
<td>
|
||||
<select name="monitorIds" size="4" multiple="multiple" onchange="updateLinkedMonitors( this )">
|
||||
<?php
|
||||
$monitors = dbFetchAll( 'select Id,Name from Monitors order by Sequence asc' );
|
||||
if ( !empty($monitor->LinkedMonitors()) )
|
||||
if ( $monitor->LinkedMonitors() )
|
||||
$monitorIds = array_flip( explode( ',', $monitor->LinkedMonitors()) );
|
||||
else
|
||||
$monitorIds = array();
|
||||
foreach ( $monitors as $linked_monitor ) {
|
||||
if ( (empty($monitor->Id()) || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor( $linked_monitor['Id'] ) ) {
|
||||
if ( (!$monitor->Id() || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor( $linked_monitor['Id'] ) ) {
|
||||
?>
|
||||
<option value="<?php echo $linked_monitor['Id'] ?>"<?php if ( array_key_exists( $linked_monitor['Id'], $monitorIds ) ) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($linked_monitor['Name']) ?></option>
|
||||
<?php
|
||||
|
@ -726,7 +729,7 @@ switch ( $tab ) {
|
|||
</tr>
|
||||
<tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPS]" value="<?php echo validHtmlStr($monitor->AnalysisFPS()) ?>" size="6"/></td></tr>
|
||||
<?php
|
||||
if ( $monitor->Type() != 'Local' && $monitor->Type() != 'File' ) {
|
||||
if ( $monitor->Type() != 'Local' && $monitor->Type() != 'File' && $monitor->Type() != 'NVSocket' ) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('MaximumFPS') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
|
||||
|
@ -822,11 +825,14 @@ switch ( $tab ) {
|
|||
</td></tr>
|
||||
<tr><td><?php echo translate('V4LCapturesPerFrame') ?></td><td><input type="number" name="newMonitor[V4LCapturesPerFrame]" value="<?php echo $monitor->V4LCapturesPerFrame()?>"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $monitor->Type() == 'Remote' ) {
|
||||
|
||||
} else if ( $monitor->Type() == 'NVSocket' ) {
|
||||
include('monitor_source_nvsocket.php');
|
||||
} else if ( $monitor->Type() == 'Remote' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
|
||||
<?php
|
||||
if ( empty($monitor->Protocol()) || $monitor->Protocol() == 'http' ) {
|
||||
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $httpMethods, $monitor->Method() ); ?></td></tr>
|
||||
<?php
|
||||
|
@ -837,7 +843,7 @@ switch ( $tab ) {
|
|||
}
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="text" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
} else if ( $monitor->Type() == 'File' ) {
|
||||
|
@ -857,14 +863,16 @@ switch ( $tab ) {
|
|||
<tr><td><?php echo translate('Options') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
}
|
||||
if ( $monitor->Type() != 'NVSocket' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('TargetColorspace') ?></td><td><select name="newMonitor[Colours]"><?php foreach ( $Colours as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Colours()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('CaptureWidth') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
|
||||
<tr><td><?php echo translate('CaptureHeight') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
|
||||
<tr><td><?php echo translate('PreserveAspect') ?></td><td><input type="checkbox" name="preserveAspectRatio" value="1"/></td></tr>
|
||||
<tr><td><?php echo translate('Orientation') ?></td><td><select name="newMonitor[Orientation]"><?php foreach ( $orientations as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Orientation()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('Orientation') ?></td><td><?php echo htmlselect( 'newMonitor[Orientation]', $orientations, $monitor->Orientation() );?></td></tr>
|
||||
<?php
|
||||
if ( $monitor->Type() == 'Local' ) {
|
||||
}
|
||||
if ( $monitor->Type() == 'Local' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts_v4l2 as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
|
@ -877,7 +885,7 @@ switch ( $tab ) {
|
|||
<?php
|
||||
if ( $monitor->Type() == 'Remote' ) {
|
||||
?>
|
||||
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( !empty($monitor->RTSPDescribe()) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( $monitor->RTSPDescribe() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
}
|
||||
break;
|
||||
|
@ -887,7 +895,7 @@ switch ( $tab ) {
|
|||
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->SaveJPEGs() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->VideoWriter() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( !empty($monitor->RecordAudio()) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
break;
|
||||
case 'timestamp' :
|
||||
|
@ -915,12 +923,12 @@ switch ( $tab ) {
|
|||
case 'control' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('Controllable') ?></td><td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( !empty($monitor->Controllable()) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('Controllable') ?></td><td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( $monitor->Controllable() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('ControlType') ?></td><td><?php echo buildSelect( "newMonitor[ControlId]", $controlTypes, 'loadLocations( this )' ); ?><?php if ( canEdit( 'Control' ) ) { ?> <a href="#" onclick="createPopup( '?view=controlcaps', 'zmControlCaps', 'controlcaps' );"><?php echo translate('Edit') ?></a><?php } ?></td></tr>
|
||||
<tr><td><?php echo translate('ControlDevice') ?></td><td><input type="text" name="newMonitor[ControlDevice]" value="<?php echo validHtmlStr($monitor->ControlDevice()) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('ControlAddress') ?></td><td><input type="text" name="newMonitor[ControlAddress]" value="<?php echo validHtmlStr($monitor->ControlAddress()) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('AutoStopTimeout') ?></td><td><input type="text" name="newMonitor[AutoStopTimeout]" value="<?php echo validHtmlStr($monitor->AutoStopTimeout()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TrackMotion') ?></td><td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( !empty($monitor->TrackMotion()) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('TrackMotion') ?></td><td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
$return_options = array(
|
||||
'-1' => translate('None'),
|
||||
|
@ -987,7 +995,7 @@ switch ( $tab ) {
|
|||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Exif') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_EXIF', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td>
|
||||
<td><input type="checkbox" name="newMonitor[Exif]" value="1"<?php if ( !empty($monitor->Exif()) ) { ?> checked="checked"<?php } ?>/></td>
|
||||
<td><input type="checkbox" name="newMonitor[Exif]" value="1"<?php if ( $monitor->Exif() ) { ?> checked="checked"<?php } ?>/></td>
|
||||
</tr>
|
||||
<?php
|
||||
break;
|
||||
|
@ -1000,7 +1008,6 @@ switch ( $tab ) {
|
|||
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,21 +18,11 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView( 'Stream' ) ) {
|
||||
if ( !canView('Stream') ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
require_once( 'includes/Monitor.php' );
|
||||
|
||||
$groupSql = '';
|
||||
if ( !empty($_REQUEST['group']) ) {
|
||||
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) );
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None' AND find_in_set( Id, '".$row['MonitorIds']."' ) ORDER BY Sequence";
|
||||
} else {
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None' ORDER BY Sequence";
|
||||
}
|
||||
|
||||
$showControl = false;
|
||||
$showZones = false;
|
||||
if ( isset( $_REQUEST['showZones'] ) ) {
|
||||
|
@ -40,12 +30,11 @@ if ( isset( $_REQUEST['showZones'] ) ) {
|
|||
$showZones = true;
|
||||
}
|
||||
}
|
||||
$monitors = array();
|
||||
$widths = array(
|
||||
'' => 'auto',
|
||||
160 => 160,
|
||||
320 => 320,
|
||||
352 => 352,
|
||||
352 => 352,
|
||||
640 => 640,
|
||||
1280 => 1280 );
|
||||
|
||||
|
@ -68,26 +57,6 @@ if ( isset( $_REQUEST['scale'] ) ) {
|
|||
if ( ! $scale )
|
||||
$scale = 100;
|
||||
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
if ( !visibleMonitor( $row['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$row['Scale'] = $scale;
|
||||
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
|
||||
if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
|
||||
$showControl = true;
|
||||
$row['connKey'] = generateConnKey();
|
||||
$monitors[] = new Monitor( $row );
|
||||
if ( ! isset( $widths[$row['Width']] ) ) {
|
||||
$widths[$row['Width']] = $row['Width'];
|
||||
}
|
||||
if ( ! isset( $heights[$row['Height']] ) ) {
|
||||
$heights[$row['Height']] = $row['Height'];
|
||||
}
|
||||
} # end foreach Monitor
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
$layouts = array(
|
||||
|
@ -114,10 +83,42 @@ else
|
|||
if ( $scale )
|
||||
$options['scale'] = $scale;
|
||||
|
||||
ob_start();
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$group_dropdowns = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
$monitors = array();
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None'";
|
||||
if ( $groupSql ) { $sql .= ' AND ' . $groupSql; };
|
||||
$sql .= 'ORDER BY Sequence';
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
if ( !visibleMonitor( $row['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$row['Scale'] = $scale;
|
||||
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
|
||||
if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
|
||||
$showControl = true;
|
||||
$row['connKey'] = generateConnKey();
|
||||
$monitors[] = new Monitor( $row );
|
||||
if ( ! isset( $widths[$row['Width']] ) ) {
|
||||
$widths[$row['Width']] = $row['Width'];
|
||||
}
|
||||
if ( ! isset( $heights[$row['Height']] ) ) {
|
||||
$heights[$row['Height']] = $row['Height'];
|
||||
}
|
||||
} # end foreach Monitor
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Montage') );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<?php
|
||||
|
@ -136,10 +137,13 @@ if ( $showZones ) {
|
|||
<?php
|
||||
}
|
||||
?>
|
||||
<a href="#" onclick="closeWindow()"><?php echo translate('Close') ?></a>
|
||||
</div>
|
||||
<h2><?php echo translate('Montage') ?></h2>
|
||||
<div id="headerControl">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
echo $group_dropdowns;
|
||||
?>
|
||||
</span>
|
||||
<span id="widthControl"><label><?php echo translate('Width') ?>:</label><?php echo htmlSelect( 'width', $widths, $options['width'], 'changeSize(this);' ); ?></span>
|
||||
<span id="heightControl"><label><?php echo translate('Height') ?>:</label><?php echo htmlSelect( 'height', $heights, $options['height'], 'changeSize(this);' ); ?></span>
|
||||
<span id="scaleControl"><label><?php echo translate('Scale') ?>:</label><?php echo htmlSelect( 'scale', $scales, $scale, 'changeScale(this);' ); ?></span>
|
||||
|
@ -150,7 +154,7 @@ if ( $showZones ) {
|
|||
<div id="monitors">
|
||||
<?php
|
||||
foreach ( $monitors as $monitor ) {
|
||||
$connkey = $monitor->connKey(); // Minor hack
|
||||
$connkey = $monitor->connKey(); // Minor hack
|
||||
?>
|
||||
<div id="monitorFrame<?php echo $monitor->Id() ?>" class="monitorFrame" title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>">
|
||||
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
||||
|
@ -224,5 +228,4 @@ foreach ( $monitors as $monitor ) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -48,68 +48,29 @@
|
|||
// It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate
|
||||
// change the playback slider to 0 and then it does not try to play at the same time it is scrubbing.
|
||||
//
|
||||
// Jul 23 2015 update:
|
||||
// - Correct problem propagating selected playback speed
|
||||
// - Change from blank monitor to specific message about no data in times with no recording
|
||||
// - Enlarge and better center fonts on labels for lines.
|
||||
// - Add support for monitor groups in selecting criteria from console
|
||||
// - Fix some no-update conditions when playback was off but scale changed or refreshed.
|
||||
// - Added translate call around buttons so as to facilitate possible translations later
|
||||
// - Removed range from/to labels on very small graphs to keep from overlapping slider
|
||||
// - Changed initial (from other page) position of slider to be in the middle to be more obvious
|
||||
//
|
||||
// Jul 29 2015 update
|
||||
// - Add live mode shots from cameras via single frame pull mode
|
||||
// - Added dynamic refresh rate based on how fast we can upload images
|
||||
// - Closed some gaps in playback frames due to time rounding in retrieval.
|
||||
// - Consolidated frame in-memory records to contiguous time rather than individual frame-seconds (still requires a good deal of browser memory)
|
||||
// - Took out a lot of the integral second rounding so that it works better at subsequent replay speeds
|
||||
//
|
||||
// Jul 30 2015 update
|
||||
// - Smoother adjustment of frame rate, fixed upper/lower limits (caching can cause runaway) (and a display, probably temporary, at the bottom)
|
||||
// - Change to using index.php?view= instead of direct access so image access is authenticated
|
||||
// - Add fractional speed for replay, and non-linear speed slider, and update current setting as slider moves (not when done)
|
||||
// - Experimenting with a black background for monitors (this should be replaced with proper CSS later)
|
||||
//
|
||||
// Aug 02, 2015 update
|
||||
// - Add max fit, make it default
|
||||
// - Remove timeline in live mode, and restore when switched back (live button becomes toggle)
|
||||
// - Add +/- zooms to individual monitors so you can adjust size, persist across reload buttons (only)
|
||||
// - Change default to 1 hour and live mode (reduce workload on initial load, let people ask for huge history amounts)
|
||||
// - Since this may be run as a standalone window for shortcuts, etc., add a "console" link to get back to the console
|
||||
//
|
||||
// August 6, 2015 update
|
||||
// - Fix regression on linkage to events when starting and staying in live mode
|
||||
// - Remove zoom/pan buttons in live mode as they are meaningless
|
||||
// - Change "fit" to a button, and remove scale when fit is in use (this means fit/live has no sliders)
|
||||
//
|
||||
// August 8, 2015 update:
|
||||
// - Optimize events query to significantly decrease load times
|
||||
// - Consolidate frames to 10 seconds not 1 for faster load and less memory usage
|
||||
// - Replace graphic image for no-data with text-on-canvas (faster)
|
||||
// - Correct sorting issue related to normalized scale so biggest goes to top left more reliably
|
||||
// - Corrections to Safari which won't support inline-flex (thanks Apple, really?!)
|
||||
//
|
||||
// August 9, 2015 updates:
|
||||
// - Add auth tokens to zms call for those using authorization
|
||||
//
|
||||
|
||||
if ( !canView( 'Events' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
require_once( 'includes/Monitor.php' );
|
||||
ob_start();
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$group_dropdowns = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
# FIXME THere is no way to select group at this time.
|
||||
if ( !empty($_REQUEST['group']) ) {
|
||||
$group = $_REQUEST['group'];
|
||||
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) );
|
||||
$monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None' AND find_in_set( Id, '".$row['MonitorIds']."' ) ";
|
||||
} else {
|
||||
$monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None'";
|
||||
$group = '';
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
|
||||
session_start();
|
||||
foreach ( array('minTime','maxTime') as $var ) {
|
||||
if ( isset( $_REQUEST[$var] ) ) {
|
||||
$_SESSION[$var] = $_REQUEST[$var];
|
||||
}
|
||||
}
|
||||
session_write_close();
|
||||
|
||||
$monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None'" . ( $groupSql ? ' AND ' . $groupSql : '');
|
||||
|
||||
// Note that this finds incomplete events as well, and any frame records written, but still cannot "see" to the end frame
|
||||
// if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large)
|
||||
|
@ -141,9 +102,9 @@ $frameSql = '
|
|||
// This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time
|
||||
|
||||
if ( ! empty( $user['MonitorIds'] ) ) {
|
||||
$eventsSql .= ' AND M.Id IN ('.$user['MonitorIds'].')';
|
||||
$monitorsSql .= ' AND Id IN ('.$user['MonitorIds'].')';
|
||||
$frameSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
|
||||
$eventsSql .= ' AND M.Id IN ('.$user['MonitorIds'].')';
|
||||
$monitorsSql .= ' AND Id IN ('.$user['MonitorIds'].')';
|
||||
$frameSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
|
||||
}
|
||||
|
||||
// Parse input parameters -- note for future, validate/clean up better in case we don't get called from self.
|
||||
|
@ -153,8 +114,9 @@ if ( ! empty( $user['MonitorIds'] ) ) {
|
|||
|
||||
|
||||
if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) {
|
||||
$maxTime = strftime("%c",time());
|
||||
$minTime = strftime("%c",time() - 3600);
|
||||
$time = time();
|
||||
$maxTime = strftime("%FT%T",$time);
|
||||
$minTime = strftime("%FT%T",$time - 3600);
|
||||
}
|
||||
if ( isset($_REQUEST['minTime']) )
|
||||
$minTime = validHtmlStr($_REQUEST['minTime']);
|
||||
|
@ -197,14 +159,13 @@ for ( $i = 0; $i < count($speeds); $i++ ) {
|
|||
if ( isset($_REQUEST['current']) )
|
||||
$defaultCurrentTime = validHtmlStr($_REQUEST['current']);
|
||||
|
||||
|
||||
$initialModeIsLive = 1;
|
||||
if ( isset($_REQUEST['live']) && $_REQUEST['live']=='0' )
|
||||
$initialModeIsLive=0;
|
||||
|
||||
$initialDisplayInterval=1000;
|
||||
$initialDisplayInterval = 1000;
|
||||
if ( isset($_REQUEST['displayinterval']) )
|
||||
$initialDisplayInterval=validHtmlStr($_REQUEST['displayinterval']);
|
||||
$initialDisplayInterval = validHtmlStr($_REQUEST['displayinterval']);
|
||||
|
||||
$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId';
|
||||
|
||||
|
@ -230,56 +191,59 @@ foreach( dbFetchAll( $monitorsSql ) as $row ) {
|
|||
|
||||
xhtmlHeaders(__FILE__, translate('MontageReview') );
|
||||
?>
|
||||
<style>
|
||||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get">
|
||||
<input type="hidden" name="view" value="montagereview"/>
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a>
|
||||
<div id="headerControl">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php echo $group_dropdowns; ?>
|
||||
</span>
|
||||
<div id="DateTimeDiv">
|
||||
<input type="datetime-local" name="minTime" id="minTime" value="<?php echo preg_replace('/ /', 'T', $minTime ) ?>" onchange="changeDateTime(this);"> to
|
||||
<input type="datetime-local" name="maxTime" id="maxTime" value="<?php echo preg_replace('/ /', 'T', $maxTime ) ?>" onchange="changeDateTime(this);">
|
||||
</div>
|
||||
<div id="ScaleDiv">
|
||||
<label for="scaleslider"><?php echo translate('Scale')?></label>
|
||||
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10" onchange="setScale(this.value);" oninput="showScale(this.value);"/>
|
||||
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
|
||||
</div>
|
||||
<div id="SpeedDiv">
|
||||
<label for="speedslider"><?php echo translate('Speed') ?></label>
|
||||
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1" onchange="setSpeed(this.value);" oninput="showSpeed(this.value);"/>
|
||||
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
|
||||
</div>
|
||||
<div style="display: inline-flex; border: 1px solid black; flex-flow: row wrap;">
|
||||
<button type="button" id="panleft" onclick="click_panleft();" >< <?php echo translate('Pan') ?></button>
|
||||
<button type="button" id="zoomin" onclick="click_zoomin();" ><?php echo translate('In +') ?></button>
|
||||
<button type="button" id="zoomout" onclick="click_zoomout();" ><?php echo translate('Out -') ?></button>
|
||||
<button type="button" id="lasteight" onclick="click_lastEight();" ><?php echo translate('8 Hour') ?></button>
|
||||
<button type="button" id="lasthour" onclick="click_lastHour();" ><?php echo translate('1 Hour') ?></button>
|
||||
<button type="button" id="allof" onclick="click_all_events();" ><?php echo translate('All Events') ?></button>
|
||||
<button type="button" id="live" onclick="setLive(1-liveMode);"><?php echo translate('Live') ?></button>
|
||||
<button type="button" id="fit" onclick="setFit(1-fitMode);" ><?php echo translate('Fit') ?></button>
|
||||
<button type="button" id="panright" onclick="click_panright();" ><?php echo translate('Pan') ?> ></button>
|
||||
</div>
|
||||
<div id="timelinediv">
|
||||
<canvas id="timeline" onmousemove="mmove(event);" ontouchmove="tmove(event);" onmousedown="mdown(event);" onmouseup="mup(event);" onmouseout="mout(event);"></canvas>
|
||||
<span id="scrubleft"></span>
|
||||
<span id="scrubright"></span>
|
||||
<span id="scruboutput"></span>
|
||||
</div>
|
||||
<h2><?php echo translate('MontageReview') ?></h2>
|
||||
</div>
|
||||
<div id="ScaleDiv">
|
||||
<label for="scaleslider"><?php echo translate('Scale')?></label>
|
||||
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10" onchange="setScale(this.value);" oninput="showScale(this.value);"/>
|
||||
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
|
||||
</div>
|
||||
<div id="SpeedDiv">
|
||||
<label for="speedslider"><?php echo translate('Speed') ?></label>
|
||||
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1" onchange="setSpeed(this.value);" oninput="showSpeed(this.value);"/>
|
||||
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
|
||||
</div>
|
||||
<div style="display: inline-flex; border: 1px solid black; flex-flow: row wrap;">
|
||||
<button type="button" id="panleft" onclick="panleft();" >< <?php echo translate('Pan') ?></button>
|
||||
<button type="button" id="zoomin" onclick="zoomin();" ><?php echo translate('In +') ?></button>
|
||||
<button type="button" id="zoomout" onclick="zoomout();" ><?php echo translate('Out -') ?></button>
|
||||
<button type="button" id="lasteight" onclick="lastEight();" ><?php echo translate('8 Hour') ?></button>
|
||||
<button type="button" id="lasthour" onclick="lastHour();" ><?php echo translate('1 Hour') ?></button>
|
||||
<button type="button" id="allof" onclick="allof();" ><?php echo translate('All Events') ?></button>
|
||||
<button type="button" id="live" onclick="setLive(1-liveMode);"><?php echo translate('Live') ?></button>
|
||||
<button type="button" id="fit" onclick="setFit(1-fitMode);" ><?php echo translate('Fit') ?></button>
|
||||
<button type="button" id="panright" onclick="panright();" ><?php echo translate('Pan') ?> ></button>
|
||||
</div>
|
||||
<div id="timelinediv">
|
||||
<canvas id="timeline" onmousemove="mmove(event);" ontouchmove="tmove(event);" onmousedown="mdown(event);" onmouseup="mup(event);" onmouseout="mout(event);"></canvas>
|
||||
<span id="scrubleft"></span>
|
||||
<span id="scrubright"></span>
|
||||
<span id="scruboutput"></span>
|
||||
</div>
|
||||
<div id="monitors">
|
||||
</div>
|
||||
</form>
|
||||
<div id="monitors">
|
||||
<?php
|
||||
// Monitor images - these had to be loaded after the monitors used were determined (after loading events)
|
||||
foreach ($monitors as $m) {
|
||||
echo '<canvas width="' . $m->Width() * $defaultScale . 'px" height="' . $m->Height() * $defaultScale . 'px" id="Monitor' . $m->Id() . '" style="border:3px solid ' . $m->WebColour() . '" onclick="clickMonitor(event,' . $m->Id() . ')">No Canvas Support!!</canvas>';
|
||||
}
|
||||
// Monitor images - these had to be loaded after the monitors used were determined (after loading events)
|
||||
foreach ($monitors as $m) {
|
||||
echo '<canvas width="' . $m->Width() * $defaultScale . '" height="' . $m->Height() * $defaultScale . '" id="Monitor' . $m->Id() . '" style="border:3px solid ' . $m->WebColour() . '" onclick="clickMonitor(event,' . $m->Id() . ')">No Canvas Support!!</canvas>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<p id="fps">evaluating fps</p>
|
||||
</div>
|
||||
<p id="fps">evaluating fps</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -18,10 +18,9 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView( 'System' ) )
|
||||
{
|
||||
$view = "error";
|
||||
return;
|
||||
if ( !canView( 'System' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
$canEdit = canEdit( 'System' );
|
||||
|
@ -45,9 +44,9 @@ $tabs['lowband'] = translate('LowBW');
|
|||
$tabs['users'] = translate('Users');
|
||||
|
||||
if ( isset($_REQUEST['tab']) )
|
||||
$tab = validHtmlStr($_REQUEST['tab']);
|
||||
$tab = validHtmlStr($_REQUEST['tab']);
|
||||
else
|
||||
$tab = "system";
|
||||
$tab = 'system';
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
|
@ -55,86 +54,81 @@ xhtmlHeaders( __FILE__, translate('Options') );
|
|||
|
||||
# Have to do this stuff up here before including header.php because fof the cookie setting
|
||||
$skin_options = array_map( 'basename', glob('skins/*',GLOB_ONLYDIR) );
|
||||
if($tab == 'skins') {
|
||||
$current_skin = $_COOKIE['zmSkin'];
|
||||
$reload = false;
|
||||
if ( isset($_GET['skin-choice']) && ( $_GET['skin-choice'] != $current_skin ) ) {
|
||||
setcookie('zmSkin',$_GET['skin-choice'], time()+3600*24*30*12*10 );
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
$current_css = $_COOKIE['zmCSS'];
|
||||
if ( isset($_GET['css-choice']) and ( $_GET['css-choice'] != $current_css ) ) {
|
||||
setcookie('zmCSS',$_GET['css-choice'], time()+3600*24*30*12*10 );
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
if ( $reload )
|
||||
echo "<script type=\"text/javascript\">if(window.opener){window.opener.location.reload();}window.location.href=\"{$_SERVER['PHP_SELF']}?view={$view}&tab={$tab}\"</script>";
|
||||
if ( $tab == 'skins' ) {
|
||||
$current_skin = $_COOKIE['zmSkin'];
|
||||
$reload = false;
|
||||
if ( isset($_GET['skin-choice']) && ( $_GET['skin-choice'] != $current_skin ) ) {
|
||||
setcookie('zmSkin',$_GET['skin-choice'], time()+3600*24*30*12*10 );
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
$current_css = $_COOKIE['zmCSS'];
|
||||
if ( isset($_GET['css-choice']) and ( $_GET['css-choice'] != $current_css ) ) {
|
||||
setcookie('zmCSS',$_GET['css-choice'], time()+3600*24*30*12*10 );
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
if ( $reload )
|
||||
echo "<script type=\"text/javascript\">if(window.opener){window.opener.location.reload();}window.location.href=\"{$_SERVER['PHP_SELF']}?view={$view}&tab={$tab}\"</script>";
|
||||
} # end if tab == skins
|
||||
|
||||
?>
|
||||
<body>
|
||||
<?php echo getNavBarHTML(); ?>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-2 sidebar">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-2 sidebar">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<?php
|
||||
foreach ( $tabs as $name=>$value )
|
||||
{
|
||||
foreach ( $tabs as $name=>$value ) {
|
||||
?>
|
||||
<li<?php echo $tab == $name ? ' class="active"' : '' ?>><a href="?view=<?php echo $view ?>&tab=<?php echo $name ?>"><?php echo $value ?></a></li>
|
||||
<li<?php echo $tab == $name ? ' class="active"' : '' ?>><a href="?view=<?php echo $view ?>&tab=<?php echo $name ?>"><?php echo $value ?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-10 col-sm-offset-2">
|
||||
<div id="options">
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-10 col-sm-offset-2">
|
||||
<div id="options">
|
||||
<?php
|
||||
if($tab == 'skins') {
|
||||
if ( $tab == 'skins' ) {
|
||||
?>
|
||||
<form name="optionsForm" class="form-horizontal" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="tab" value="<?php echo $tab ?>"/>
|
||||
<div class="form-group">
|
||||
<label for="skin-choice" class="col-sm-3 control-label">ZM_SKIN</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="skin-choice" class="form-control">
|
||||
<?php
|
||||
foreach($skin_options as $dir) {
|
||||
echo '<option value="'.$dir.'" '.($current_skin==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<span class="help-block"><?php echo translate('SkinDescription'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="css-choice" class="col-sm-3 control-label">ZM_CSS</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="css-choice" class="form-control">
|
||||
<?php
|
||||
foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDIR) ) as $dir) {
|
||||
echo '<option value="'.$dir.'" '.($current_css==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<span class="help-block"><?php echo translate('CSSDescription'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" class="btn btn-primary btn-lg" value="<?php echo translate('Save') ?>"<?php echo $canEdit?'':' disabled="disabled"' ?>/>
|
||||
</div>
|
||||
</form>
|
||||
<form name="optionsForm" class="form-horizontal" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="tab" value="<?php echo $tab ?>"/>
|
||||
<div class="form-group">
|
||||
<label for="skin-choice" class="col-sm-3 control-label">SKIN</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="skin-choice" class="form-control">
|
||||
<?php
|
||||
foreach($skin_options as $dir) {
|
||||
echo '<option value="'.$dir.'" '.($current_skin==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<span class="help-block"><?php echo translate('SkinDescription'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="css-choice" class="col-sm-3 control-label">CSS</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="css-choice" class="form-control">
|
||||
<?php
|
||||
foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDIR) ) as $dir) {
|
||||
echo '<option value="'.$dir.'" '.($current_css==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<span class="help-block"><?php echo translate('CSSDescription'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" class="btn btn-primary btn-lg" value="<?php echo translate('Save') ?>"<?php echo $canEdit?'':' disabled="disabled"' ?>/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
}
|
||||
elseif ( $tab == "users" )
|
||||
{
|
||||
} else if ( $tab == 'users' ) {
|
||||
?>
|
||||
<form name="userForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
|
@ -159,24 +153,20 @@ elseif ( $tab == "users" )
|
|||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$sql = "select * from Monitors order by Sequence asc";
|
||||
$sql = 'select * from Monitors order by Sequence asc';
|
||||
$monitors = array();
|
||||
foreach( dbFetchAll( $sql ) as $monitor )
|
||||
{
|
||||
$monitors[$monitor['Id']] = $monitor;
|
||||
foreach( dbFetchAll( $sql ) as $monitor ) {
|
||||
$monitors[$monitor['Id']] = $monitor;
|
||||
}
|
||||
|
||||
$sql = "select * from Users";
|
||||
foreach( dbFetchAll( $sql ) as $row )
|
||||
{
|
||||
$userMonitors = array();
|
||||
if ( !empty($row['MonitorIds']) )
|
||||
{
|
||||
foreach ( explode( ",", $row['MonitorIds'] ) as $monitorId )
|
||||
{
|
||||
$userMonitors[] = $monitors[$monitorId]['Name'];
|
||||
}
|
||||
$sql = 'select * from Users';
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
$userMonitors = array();
|
||||
if ( !empty($row['MonitorIds']) ) {
|
||||
foreach ( explode( ',', $row['MonitorIds'] ) as $monitorId ) {
|
||||
$userMonitors[] = $monitors[$monitorId]['Name'];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class="colUsername"><?php echo makePopupLink( '?view=user&uid='.$row['Id'], 'zmUser', 'user', validHtmlStr($row['Username']).($user['Username']==$row['Username']?"*":""), $canEdit ) ?></td>
|
||||
|
@ -260,7 +250,9 @@ elseif ( $tab == "users" )
|
|||
</tbody>
|
||||
</table>
|
||||
<div id="contentButtons">
|
||||
<input type="button" value="<?php echo translate('AddNewStorage') ?>" onclick="createPopup( '?view=storage&id=0', 'zmStorage', 'storage' );"<?php if ( !canEdit( 'System' ) ) { ?> disabled="disabled"<?php } ?>/><input type="submit" name="deleteBtn" value="<?php echo translate('Delete') ?>" disabled="disabled"/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow();"/>
|
||||
<input type="button" value="<?php echo translate('AddNewStorage') ?>" onclick="createPopup( '?view=storage&id=0', 'zmStorage', 'storage' );"<?php if ( !canEdit( 'System' ) ) { ?> disabled="disabled"<?php } ?>/>
|
||||
<input type="submit" name="deleteBtn" value="<?php echo translate('Delete') ?>" disabled="disabled"/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow();"/>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
|
@ -287,33 +279,25 @@ elseif ( $tab == "users" )
|
|||
<label for="<?php echo $name ?>" class="col-sm-3 control-label"><?php echo $shortName ?></label>
|
||||
<div class="col-sm-6">
|
||||
<?php
|
||||
if ( $value['Type'] == "boolean" )
|
||||
{
|
||||
if ( $value['Type'] == "boolean" ) {
|
||||
?>
|
||||
<input type="checkbox" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="1"<?php if ( $value['Value'] ) { ?> checked="checked"<?php } ?><?php echo $canEdit?'':' disabled="disabled"' ?>/>
|
||||
<?php
|
||||
}
|
||||
elseif ( preg_match( "/\|/", $value['Hint'] ) )
|
||||
{
|
||||
} elseif ( preg_match( "/\|/", $value['Hint'] ) ) {
|
||||
?>
|
||||
<?php
|
||||
$options = explode( '|', $value['Hint'] );
|
||||
if ( count( $options ) > 3 )
|
||||
{
|
||||
if ( count( $options ) > 3 ) {
|
||||
?>
|
||||
<select class="form-control" name="newConfig[<?php echo $name ?>]"<?php echo $canEdit?'':' disabled="disabled"' ?>>
|
||||
<?php
|
||||
foreach ( $options as $option )
|
||||
{
|
||||
if ( preg_match( '/^([^=]+)=(.+)$/', $option, $matches ) )
|
||||
{
|
||||
$optionLabel = $matches[1];
|
||||
$optionValue = $matches[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
$optionLabel = $optionValue = $option;
|
||||
}
|
||||
foreach ( $options as $option ) {
|
||||
if ( preg_match( '/^([^=]+)=(.+)$/', $option, $matches ) ) {
|
||||
$optionLabel = $matches[1];
|
||||
$optionValue = $matches[2];
|
||||
} else {
|
||||
$optionLabel = $optionValue = $option;
|
||||
}
|
||||
?>
|
||||
<option value="<?php echo $optionValue ?>"<?php if ( $value['Value'] == $optionValue ) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($optionLabel) ?></option>
|
||||
<?php
|
||||
|
@ -321,18 +305,12 @@ elseif ( $tab == "users" )
|
|||
?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( $options as $option )
|
||||
{
|
||||
if ( preg_match( '/^([^=]+)=(.+)$/', $option ) )
|
||||
{
|
||||
} else {
|
||||
foreach ( $options as $option ) {
|
||||
if ( preg_match( '/^([^=]+)=(.+)$/', $option ) ) {
|
||||
$optionLabel = $matches[1];
|
||||
$optionValue = $matches[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$optionLabel = $optionValue = $option;
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -56,7 +56,7 @@ xhtmlHeaders(__FILE__, translate('Storage')." - ".$newStorage['Name'] );
|
|||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Path') ?></th>
|
||||
<td><input type="url" name="newStorage[Path]" value="<?php echo $newStorage['Path'] ?>"/></td>
|
||||
<td><input type="text" name="newStorage[Path]" value="<?php echo $newStorage['Path'] ?>"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -710,7 +710,7 @@ xhtmlHeaders(__FILE__, translate('Timeline') );
|
|||
<div id="topPanel" class="graphWidth">
|
||||
<div id="imagePanel">
|
||||
<div id="image" class="imageHeight">
|
||||
<img id="imageSrc" class="imageWidth" src="graphics/transparent.gif" alt="<?php echo translate('ViewEvent') ?>" title="<?php echo translate('ViewEvent') ?>"/>
|
||||
<img id="imageSrc" class="imageWidth" src="graphics/transparent.png" alt="<?php echo translate('ViewEvent') ?>" title="<?php echo translate('ViewEvent') ?>"/>
|
||||
<?php
|
||||
if ( 0 ) {
|
||||
//due to chrome bug, has to enable https://code.google.com/p/chromium/issues/detail?id=472300
|
||||
|
@ -852,7 +852,7 @@ foreach( array_keys($monEventSlots) as $monitorId ) {
|
|||
foreach( array_keys($monEventSlots) as $monitorId ) {
|
||||
?>
|
||||
<span class="keyEntry"><?php echo $monitors[$monitorId]['Name'] ?>
|
||||
<img id="keyBox<?php echo $monitorId ?>" class="keyBox monitorColour<?php echo $monitorId ?>" src="graphics/transparent.gif" alt="<?php echo $monitors[$monitorId]['Name'] ?>"/>
|
||||
<img id="keyBox<?php echo $monitorId ?>" class="keyBox monitorColour<?php echo $monitorId ?>" src="graphics/transparent.png" alt="<?php echo $monitors[$monitorId]['Name'] ?>"/>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
|
|
|
@ -283,7 +283,9 @@ for ( $i = 0; $i < $pointCols; $i++ )
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<input id="pauseBtn" type="button" value="<?php echo translate('Pause') ?>" onclick="streamCmdPauseToggle()"/><input type="submit" id="submitBtn" name="submitBtn" value="<?php echo translate('Save') ?>" onclick="return saveChanges( this )"<?php if (!canEdit( 'Monitors' ) || (false && $selfIntersecting)) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="refreshParentWindow(); closeWindow();"/>
|
||||
<input id="pauseBtn" type="button" value="<?php echo translate('Pause') ?>" onclick="streamCmdPauseToggle()"/>
|
||||
<input type="submit" id="submitBtn" name="submitBtn" value="<?php echo translate('Save') ?>" onclick="return saveChanges( this )"<?php if (!canEdit( 'Monitors' ) || (false && $selfIntersecting)) { ?> disabled="disabled"<?php } ?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="refreshParentWindow(); closeWindow();"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -26,10 +26,10 @@ if ( !canView( 'Monitors' ) ) {
|
|||
$mid = validInt($_REQUEST['mid']);
|
||||
$monitor = new Monitor( $mid );
|
||||
# Width() and Height() are already rotated
|
||||
$minX = 0;
|
||||
$maxX = $monitor->Width()-1;
|
||||
$minY = 0;
|
||||
$maxY = $monitor->Height()-1;
|
||||
$minX = 0;
|
||||
$maxX = $monitor->Width()-1;
|
||||
$minY = 0;
|
||||
$maxY = $monitor->Height()-1;
|
||||
|
||||
$zones = array();
|
||||
foreach( dbFetchAll( 'SELECT * FROM Zones WHERE MonitorId=? ORDER BY Area DESC', NULL, array($mid) ) as $row ) {
|
||||
|
@ -71,8 +71,7 @@ xhtmlHeaders(__FILE__, translate('Zones') );
|
|||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach( $zones as $zone )
|
||||
{
|
||||
foreach( $zones as $zone ) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="colName"><a href="#" onclick="streamCmdQuit( true ); createPopup( '?view=zone&mid=<?php echo $mid ?>&zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width() ?>, <?php echo $monitor->Height() ?> ); return( false );"><?php echo $zone['Name'] ?></a></td>
|
||||
|
@ -86,12 +85,12 @@ foreach( $zones as $zone )
|
|||
</tbody>
|
||||
</table>
|
||||
<div class="ZonesImage" style="position:relative; clear:both;">
|
||||
<?php echo getStreamHTML( $monitor ); ?>
|
||||
<svg class="zones" width="<?php echo $monitor->Width() ?>" height="<?php echo $monitor->Height() ?>" style="position:absolute; top: 0; left: 0; background: none;">
|
||||
<?php echo getStreamHTML( $monitor ); ?>
|
||||
<svg class="zones" width="<?php echo $monitor->Width() ?>" height="<?php echo $monitor->Height() ?>" style="position:absolute; top: 0; left: 0; background: none;">
|
||||
<?php
|
||||
foreach( array_reverse($zones) as $zone ) {
|
||||
?>
|
||||
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="streamCmdQuit( true ); createPopup( '?view=zone&mid=<?php echo $mid ?>&zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/>
|
||||
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="streamCmdQuit( true ); createPopup( '?view=zone&mid=<?php echo $mid ?>&zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/>
|
||||
<?php
|
||||
} // end foreach zone
|
||||
?>
|
||||
|
|
Loading…
Reference in New Issue