Merge branch 'release-1.34' of github.com:ZoneMinder/zoneminder into release-1.34

This commit is contained in:
Isaac Connor 2020-05-08 17:26:02 -04:00
commit 1f6e68c129
31 changed files with 732 additions and 528 deletions

View File

@ -28,7 +28,7 @@
%global _hardened_build 1 %global _hardened_build 1
Name: zoneminder Name: zoneminder
Version: 1.34.10 Version: 1.34.11
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons

View File

@ -33,37 +33,33 @@
// Class used for storing a box, which is defined as a region // Class used for storing a box, which is defined as a region
// defined by two coordinates // defined by two coordinates
// //
class Box class Box {
{
private: private:
Coord lo, hi; Coord lo, hi;
Coord size; Coord size;
public: public:
inline Box() inline Box() { }
{
}
explicit inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { } explicit inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { }
inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { } inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { }
inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { } inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { }
inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { } inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { }
inline const Coord &Lo() const { return( lo ); } inline const Coord &Lo() const { return lo; }
inline int LoX() const { return( lo.X() ); } inline int LoX() const { return lo.X(); }
inline int LoY() const { return( lo.Y() ); } inline int LoY() const { return lo.Y(); }
inline const Coord &Hi() const { return( hi ); } inline const Coord &Hi() const { return hi; }
inline int HiX() const { return( hi.X() ); } inline int HiX() const { return hi.X(); }
inline int HiY() const { return( hi.Y() ); } inline int HiY() const { return hi.Y(); }
inline const Coord &Size() const { return( size ); } inline const Coord &Size() const { return size; }
inline int Width() const { return( size.X() ); } inline int Width() const { return size.X(); }
inline int Height() const { return( size.Y() ); } inline int Height() const { return size.Y(); }
inline int Area() const { return( size.X()*size.Y() ); } inline int Area() const { return size.X()*size.Y(); }
inline const Coord Centre() const inline const Coord Centre() const {
{
int mid_x = int(round(lo.X()+(size.X()/2.0))); int mid_x = int(round(lo.X()+(size.X()/2.0)));
int mid_y = int(round(lo.Y()+(size.Y()/2.0))); int mid_y = int(round(lo.Y()+(size.Y()/2.0)));
return( Coord( mid_x, mid_y ) ); return Coord( mid_x, mid_y );
} }
inline bool Inside( const Coord &coord ) const inline bool Inside( const Coord &coord ) const
{ {

View File

@ -63,7 +63,9 @@ void zmLoadConfig() {
closedir(configSubFolder); closedir(configSubFolder);
} }
zmDbConnect(); if ( !zmDbConnect() ) {
Fatal("Can't connect to db. Can't continue.");
}
config.Load(); config.Load();
config.Assign(); config.Assign();

View File

@ -25,8 +25,7 @@
// //
// Class used for storing an x,y pair, i.e. a coordinate // Class used for storing an x,y pair, i.e. a coordinate
// //
class Coord class Coord {
{
private: private:
int x, y; int x, y;
@ -44,8 +43,7 @@ public:
inline int &Y() { return( y ); } inline int &Y() { return( y ); }
inline const int &Y() const { return( y ); } inline const int &Y() const { return( y ); }
inline static Coord Range( const Coord &coord1, const Coord &coord2 ) inline static Coord Range( const Coord &coord1, const Coord &coord2 ) {
{
Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 );
return( result ); return( result );
} }

View File

@ -164,7 +164,22 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->Orientation = (Monitor::Orientation)(dbrow[8] == NULL ? 0 : atoi(dbrow[8])); event_data->Orientation = (Monitor::Orientation)(dbrow[8] == NULL ? 0 : atoi(dbrow[8]));
mysql_free_result(result); mysql_free_result(result);
Storage * storage = new Storage(event_data->storage_id); if ( !monitor ) {
monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY);
} else if ( monitor->Id() != event_data->monitor_id ) {
delete monitor;
monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY);
}
if ( !monitor ) {
Fatal("Unable to load monitor id %d for streaming", event_data->monitor_id);
}
if ( !storage ) {
storage = new Storage(event_data->storage_id);
} else if ( storage->Id() != event_data->storage_id ) {
delete storage;
storage = new Storage(event_data->storage_id);
}
const char *storage_path = storage->Path(); const char *storage_path = storage->Path();
if ( event_data->scheme == Storage::DEEP ) { if ( event_data->scheme == Storage::DEEP ) {
@ -206,7 +221,6 @@ bool EventStream::loadEventData(uint64_t event_id) {
staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id,
event_data->event_id); event_data->event_id);
} }
delete storage; storage = NULL;
updateFrameRate((double)event_data->frame_count/event_data->duration); updateFrameRate((double)event_data->frame_count/event_data->duration);
Debug(3, "fps set by frame_count(%d)/duration(%f)", Debug(3, "fps set by frame_count(%d)/duration(%f)",
@ -246,7 +260,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->frames[i-1].timestamp = last_timestamp + ((i-last_id)*frame_delta); event_data->frames[i-1].timestamp = last_timestamp + ((i-last_id)*frame_delta);
event_data->frames[i-1].offset = event_data->frames[i-1].timestamp - event_data->start_time; event_data->frames[i-1].offset = event_data->frames[i-1].timestamp - event_data->start_time;
event_data->frames[i-1].in_db = false; event_data->frames[i-1].in_db = false;
Debug(3,"Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", Debug(3, "Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)",
i, i,
event_data->frames[i-1].timestamp, event_data->frames[i-1].timestamp,
event_data->frames[i-1].offset, event_data->frames[i-1].offset,
@ -277,7 +291,10 @@ bool EventStream::loadEventData(uint64_t event_id) {
mysql_free_result(result); mysql_free_result(result);
if ( event_data->video_file[0] ) { if ( event_data->video_file[0] || (monitor->GetOptVideoWriter() > 0) ) {
if ( !event_data->video_file[0] ) {
snprintf(event_data->video_file, sizeof(event_data->video_file), "%" PRIu64 "-%s", event_data->event_id, "video.mp4");
}
std::string filepath = std::string(event_data->path) + "/" + std::string(event_data->video_file); std::string filepath = std::string(event_data->path) + "/" + std::string(event_data->video_file);
//char filepath[PATH_MAX]; //char filepath[PATH_MAX];
//snprintf(filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file); //snprintf(filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file);
@ -305,7 +322,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
void EventStream::processCommand(const CmdMsg *msg) { void EventStream::processCommand(const CmdMsg *msg) {
Debug(2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0]); Debug(2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0]);
// Check for incoming command // Check for incoming command
switch( (MsgCommand)msg->msg_data[0] ) { switch ( (MsgCommand)msg->msg_data[0] ) {
case CMD_PAUSE : case CMD_PAUSE :
Debug(1, "Got PAUSE command"); Debug(1, "Got PAUSE command");
@ -657,7 +674,8 @@ bool EventStream::sendFrame(int delta_us) {
Image *send_image = prepareImage(&image); Image *send_image = prepareImage(&image);
if ( !vid_stream ) { if ( !vid_stream ) {
vid_stream = new VideoStream("pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height()); vid_stream = new VideoStream("pipe:", format, bitrate, effective_fps,
send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height());
fprintf(stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType()); fprintf(stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType());
vid_stream->OpenStream(); vid_stream->OpenStream();
} }
@ -700,9 +718,10 @@ Debug(1, "Loading image");
} else if ( ffmpeg_input ) { } else if ( ffmpeg_input ) {
// Get the frame from the mp4 input // Get the frame from the mp4 input
Debug(1,"Getting frame from ffmpeg"); Debug(1,"Getting frame from ffmpeg");
AVFrame *frame;
FrameData *frame_data = &event_data->frames[curr_frame_id-1]; FrameData *frame_data = &event_data->frames[curr_frame_id-1];
frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id(), frame_data->offset ); AVFrame *frame = ffmpeg_input->get_frame(
ffmpeg_input->get_video_stream_id(),
frame_data->offset);
if ( frame ) { if ( frame ) {
image = new Image(frame); image = new Image(frame);
//av_frame_free(&frame); //av_frame_free(&frame);
@ -982,8 +1001,8 @@ void EventStream::runStream() {
// you can calculate the relationship between now and the start // you can calculate the relationship between now and the start
// or calc the relationship from the last frame. I think from the start is better as it self-corrects // or calc the relationship from the last frame. I think from the start is better as it self-corrects
if ( send_frame && type != STREAM_MPEG ) { if ( send_frame && (type != STREAM_MPEG) ) {
if ( delta_us > 0) { if ( delta_us > 0 ) {
if ( delta_us > MAX_SLEEP_USEC ) { if ( delta_us > MAX_SLEEP_USEC ) {
Debug(1, "Limiting sleep to %d because calculated sleep is too long %d", MAX_SLEEP_USEC, delta_us); Debug(1, "Limiting sleep to %d because calculated sleep is too long %d", MAX_SLEEP_USEC, delta_us);
delta_us = MAX_SLEEP_USEC; delta_us = MAX_SLEEP_USEC;
@ -1026,18 +1045,12 @@ void EventStream::runStream() {
closeComms(); closeComms();
} // void EventStream::runStream() } // void EventStream::runStream()
void EventStream::setStreamStart( uint64_t init_event_id, unsigned int init_frame_id=0 ) { void EventStream::setStreamStart(
uint64_t init_event_id,
unsigned int init_frame_id=0) {
loadInitialEventData(init_event_id, init_frame_id); loadInitialEventData(init_event_id, init_frame_id);
if ( !(monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY)) ) { } // end void EventStream::setStreamStart(init_event_id,init_frame_id=0)
Fatal("Unable to load monitor id %d for streaming", event_data->monitor_id);
return;
}
}
void EventStream::setStreamStart(int monitor_id, time_t event_time) { void EventStream::setStreamStart(int monitor_id, time_t event_time) {
loadInitialEventData(monitor_id, event_time); loadInitialEventData(monitor_id, event_time);
if ( !(monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY)) ) {
Fatal("Unable to load monitor id %d for streaming", monitor_id);
return;
}
} }

View File

@ -20,9 +20,6 @@
#ifndef ZM_EVENTSTREAM_H #ifndef ZM_EVENTSTREAM_H
#define ZM_EVENTSTREAM_H #define ZM_EVENTSTREAM_H
#include <set>
#include <map>
#include "zm_image.h" #include "zm_image.h"
#include "zm_stream.h" #include "zm_stream.h"
#include "zm_video.h" #include "zm_video.h"
@ -83,7 +80,6 @@ class EventStream : public StreamBase {
struct timeval start; // clock time when started the event struct timeval start; // clock time when started the event
EventData *event_data; EventData *event_data;
FFmpeg_Input *ffmpeg_input;
protected: protected:
bool loadEventData( uint64_t event_id ); bool loadEventData( uint64_t event_id );
@ -95,24 +91,41 @@ class EventStream : public StreamBase {
bool sendFrame( int delta_us ); bool sendFrame( int delta_us );
public: public:
EventStream() { EventStream() :
mode = DEFAULT_MODE; mode(DEFAULT_MODE),
replay_rate = DEFAULT_RATE; forceEventChange(false),
curr_frame_id(0),
forceEventChange = false; curr_stream_time(0.0),
send_frame(false),
curr_frame_id = 0; event_data(0),
curr_stream_time = 0.0; storage(NULL),
send_frame = false; ffmpeg_input(NULL),
event_data = 0;
// Used when loading frames from an mp4 // Used when loading frames from an mp4
input_codec_context = 0; input_codec_context(0),
input_codec = 0; input_codec(0)
{}
~EventStream() {
if ( event_data ) {
if ( event_data->frames ) {
delete[] event_data->frames;
event_data->frames = NULL;
}
delete event_data;
event_data = NULL;
}
if ( monitor ) {
delete monitor;
monitor = NULL;
}
if ( storage ) {
delete storage;
storage = NULL;
}
if ( ffmpeg_input ) {
delete ffmpeg_input;
ffmpeg_input = NULL; ffmpeg_input = NULL;
} }
}
void setStreamStart( uint64_t init_event_id, unsigned int init_frame_id ); void setStreamStart( uint64_t init_event_id, unsigned int init_frame_id );
void setStreamStart( int monitor_id, time_t event_time ); void setStreamStart( int monitor_id, time_t event_time );
void setStreamMode( StreamMode p_mode ) { void setStreamMode( StreamMode p_mode ) {
@ -121,6 +134,8 @@ class EventStream : public StreamBase {
void runStream(); void runStream();
Image *getImage(); Image *getImage();
private: private:
Storage *storage;
FFmpeg_Input *ffmpeg_input;
AVCodecContext *input_codec_context; AVCodecContext *input_codec_context;
AVCodec *input_codec; AVCodec *input_codec;
}; };

View File

@ -321,6 +321,7 @@ void zm_dump_codecpar(const AVCodecParameters *par);
frame->pts \ frame->pts \
); );
#if LIBAVUTIL_VERSION_CHECK(54, 4, 0, 74, 100)
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \ #define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
text, \ text, \
frame->format, \ frame->format, \
@ -331,6 +332,18 @@ void zm_dump_codecpar(const AVCodecParameters *par);
frame->pts \ frame->pts \
); );
#else
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
text, \
frame->format, \
"unsupported", \
frame->width, \
frame->height, \
frame->linesize[0], frame->linesize[1], \
frame->pts \
);
#endif
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100) #if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
#define zm_av_packet_unref( packet ) av_packet_unref( packet ) #define zm_av_packet_unref( packet ) av_packet_unref( packet )
#define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src ) #define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src )

View File

@ -15,10 +15,26 @@ FFmpeg_Input::FFmpeg_Input() {
FFmpeg_Input::~FFmpeg_Input() { FFmpeg_Input::~FFmpeg_Input() {
if ( streams ) { if ( streams ) {
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
avcodec_close(streams[i].context);
streams[i].context = NULL;
}
delete streams; delete streams;
streams = NULL; streams = NULL;
} }
} if ( frame ) {
av_frame_free(&frame);
frame = NULL;
}
if ( input_format_context ) {
#if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0)
av_close_input_file(input_format_context);
#else
avformat_close_input(&input_format_context);
#endif
input_format_context = NULL;
}
} // end ~FFmpeg_Input()
int FFmpeg_Input::Open(const char *filepath) { int FFmpeg_Input::Open(const char *filepath) {
@ -90,6 +106,7 @@ int FFmpeg_Input::Open(const char *filepath) {
avcodec_free_context(&streams[i].context); avcodec_free_context(&streams[i].context);
#endif #endif
avformat_close_input(&input_format_context); avformat_close_input(&input_format_context);
input_format_context = NULL;
return error; return error;
} }
} // end foreach stream } // end foreach stream
@ -103,7 +120,6 @@ int FFmpeg_Input::Open(const char *filepath) {
} // end int FFmpeg_Input::Open( const char * filepath ) } // end int FFmpeg_Input::Open( const char * filepath )
AVFrame *FFmpeg_Input::get_frame(int stream_id) { AVFrame *FFmpeg_Input::get_frame(int stream_id) {
int frameComplete = false; int frameComplete = false;
AVPacket packet; AVPacket packet;
av_init_packet(&packet); av_init_packet(&packet);
@ -139,8 +155,8 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
} }
ret = zm_send_packet_receive_frame(context, frame, packet); ret = zm_send_packet_receive_frame(context, frame, packet);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("Unable to decode frame at frame %d: %s, continuing", Error("Unable to decode frame at frame %d: %d %s, continuing",
streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str()); streams[packet.stream_index].frame_count, ret, av_make_error_string(ret).c_str());
zm_av_packet_unref(&packet); zm_av_packet_unref(&packet);
av_frame_free(&frame); av_frame_free(&frame);
continue; continue;
@ -214,12 +230,14 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) {
if ( frame->pts <= seek_target ) { if ( frame->pts <= seek_target ) {
zm_dump_frame(frame, "pts <= seek_target"); zm_dump_frame(frame, "pts <= seek_target");
while ( frame && (frame->pts < seek_target) ) { while ( frame && (frame->pts < seek_target) ) {
if ( !get_frame(stream_id) ) if ( !get_frame(stream_id) ) {
Warning("Got no frame. returning nothing");
return frame; return frame;
} }
}
zm_dump_frame(frame, "frame->pts <= seek_target, got");
return frame; return frame;
} }
return get_frame(stream_id); return get_frame(stream_id);
} // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at) } // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at)

View File

@ -48,6 +48,8 @@ static short *g_v_table;
static short *g_u_table; static short *g_u_table;
static short *b_u_table; static short *b_u_table;
struct SwsContext *sws_convert_context = NULL;
jpeg_compress_struct *Image::writejpg_ccinfo[101] = { 0 }; jpeg_compress_struct *Image::writejpg_ccinfo[101] = { 0 };
jpeg_compress_struct *Image::encodejpg_ccinfo[101] = { 0 }; jpeg_compress_struct *Image::encodejpg_ccinfo[101] = { 0 };
jpeg_decompress_struct *Image::readjpg_dcinfo = 0; jpeg_decompress_struct *Image::readjpg_dcinfo = 0;
@ -160,15 +162,17 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin
update_function_pointers(); update_function_pointers();
} }
Image::Image( const AVFrame *frame ) { Image::Image(const AVFrame *frame) {
AVFrame *dest_frame = zm_av_frame_alloc(); AVFrame *dest_frame = zm_av_frame_alloc();
text[0] = '\0'; text[0] = '\0';
width = frame->width; width = frame->width;
height = frame->height; height = frame->height;
pixels = width*height; pixels = width*height;
colours = ZM_COLOUR_RGB32; colours = ZM_COLOUR_RGB32;
subpixelorder = ZM_SUBPIX_ORDER_RGBA; subpixelorder = ZM_SUBPIX_ORDER_RGBA;
size = pixels*colours; size = pixels*colours;
buffer = 0; buffer = 0;
holdbuffer = 0; holdbuffer = 0;
@ -183,26 +187,28 @@ Image::Image( const AVFrame *frame ) {
#endif #endif
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext = sws_getContext( sws_convert_context = sws_getCachedContext(
sws_convert_context,
width, width,
height, height,
(AVPixelFormat)frame->format, (AVPixelFormat)frame->format,
width, height, width, height,
AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL, AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL,
NULL, NULL); NULL, NULL);
if ( mConvertContext == NULL ) if ( sws_convert_context == NULL )
Fatal( "Unable to create conversion context" ); Fatal("Unable to create conversion context");
if ( sws_scale(mConvertContext, frame->data, frame->linesize, 0, frame->height, dest_frame->data, dest_frame->linesize) < 0 ) if ( sws_scale(sws_convert_context, frame->data, frame->linesize, 0, frame->height,
dest_frame->data, dest_frame->linesize) < 0 )
Fatal("Unable to convert raw format %u to target format %u", frame->format, AV_PIX_FMT_RGBA); Fatal("Unable to convert raw format %u to target format %u", frame->format, AV_PIX_FMT_RGBA);
#else // HAVE_LIBSWSCALE #else // HAVE_LIBSWSCALE
Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras"); Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras");
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
av_frame_free( &dest_frame ); av_frame_free(&dest_frame);
update_function_pointers(); update_function_pointers();
} } // end Image::Image(const AVFrame *frame)
Image::Image( const Image &p_image ) { Image::Image(const Image &p_image) {
if ( !initialised ) if ( !initialised )
Initialise(); Initialise();
width = p_image.width; width = p_image.width;
@ -215,7 +221,7 @@ Image::Image( const Image &p_image ) {
holdbuffer = 0; holdbuffer = 0;
AllocImgBuffer(size); AllocImgBuffer(size);
(*fptr_imgbufcpy)(buffer, p_image.buffer, size); (*fptr_imgbufcpy)(buffer, p_image.buffer, size);
strncpy( text, p_image.text, sizeof(text) ); strncpy(text, p_image.text, sizeof(text));
update_function_pointers(); update_function_pointers();
} }
@ -225,7 +231,7 @@ Image::~Image() {
/* Should be called as part of program shutdown to free everything */ /* Should be called as part of program shutdown to free everything */
void Image::Deinitialise() { void Image::Deinitialise() {
if ( initialised ) { if ( !initialised ) return;
/* /*
delete[] y_table; delete[] y_table;
delete[] uv_table; delete[] uv_table;
@ -252,8 +258,12 @@ void Image::Deinitialise() {
writejpg_ccinfo[quality] = NULL; writejpg_ccinfo[quality] = NULL;
} }
} // end foreach quality } // end foreach quality
if ( sws_convert_context ) {
sws_freeContext(sws_convert_context);
sws_convert_context = NULL;
} }
} } // end void Image::Deinitialise()
void Image::Initialise() { void Image::Initialise() {
/* Assign the blend pointer to function */ /* Assign the blend pointer to function */
@ -655,15 +665,16 @@ void Image::Assign( const Image &image ) {
return; return;
} }
if ( !buffer || image.width != width || image.height != height || image.colours != colours || image.subpixelorder != subpixelorder) { if ( !buffer || image.width != width || image.height != height
|| image.colours != colours || image.subpixelorder != subpixelorder) {
if (holdbuffer && buffer) { if ( holdbuffer && buffer ) {
if (new_size > allocation) { if ( new_size > allocation ) {
Error("Held buffer is undersized for assigned buffer"); Error("Held buffer is undersized for assigned buffer");
return; return;
} }
} else { } else {
if(new_size > allocation || !buffer) { if ( new_size > allocation || !buffer) {
// DumpImgBuffer(); This is also done in AllocImgBuffer // DumpImgBuffer(); This is also done in AllocImgBuffer
AllocImgBuffer(new_size); AllocImgBuffer(new_size);
} }

View File

@ -121,7 +121,7 @@ protected:
}; };
inline void DumpImgBuffer() { inline void DumpImgBuffer() {
DumpBuffer(buffer,buffertype); DumpBuffer(buffer, buffertype);
buffer = NULL; buffer = NULL;
allocation = 0; allocation = 0;
} }

View File

@ -1655,7 +1655,7 @@ bool Monitor::Analyse() {
Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images", Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images",
name, image_count, event->Id(), event->Frames(), event->AlarmFrames()); name, image_count, event->Id(), event->Frames(), event->AlarmFrames());
//if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE )
if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) { if ( ( function != MOCORD && function != RECORD ) || event_close_mode == CLOSE_ALARM ) {
shared_data->state = state = IDLE; shared_data->state = state = IDLE;
Info("%s: %03d - Closing event %" PRIu64 ", alarm end%s", Info("%s: %03d - Closing event %" PRIu64 ", alarm end%s",
name, image_count, event->Id(), (function==MOCORD)?", section truncated":""); name, image_count, event->Id(), (function==MOCORD)?", section truncated":"");

View File

@ -26,11 +26,9 @@
#include <cmath> #include <cmath>
#endif #endif
void Polygon::calcArea() void Polygon::calcArea() {
{
double float_area = 0.0L; double float_area = 0.0L;
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
{
double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L; double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L;
float_area += trap_area; float_area += trap_area;
//printf( "%.2f (%.2f)\n", float_area, trap_area ); //printf( "%.2f (%.2f)\n", float_area, trap_area );
@ -38,13 +36,11 @@ void Polygon::calcArea()
area = (int)round(fabs(float_area)); area = (int)round(fabs(float_area));
} }
void Polygon::calcCentre() void Polygon::calcCentre() {
{
if ( !area && n_coords ) if ( !area && n_coords )
calcArea(); calcArea();
double float_x = 0.0L, float_y = 0.0L; double float_x = 0.0L, float_y = 0.0L;
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
{
float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2))); float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2)));
float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2))); float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2)));
} }
@ -54,16 +50,14 @@ void Polygon::calcCentre()
centre = Coord( (int)round(float_x), (int)round(float_y) ); centre = Coord( (int)round(float_x), (int)round(float_y) );
} }
Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords ) Polygon::Polygon(int p_n_coords, const Coord *p_coords) : n_coords( p_n_coords ) {
{
coords = new Coord[n_coords]; coords = new Coord[n_coords];
int min_x = -1; int min_x = -1;
int max_x = -1; int max_x = -1;
int min_y = -1; int min_y = -1;
int max_y = -1; int max_y = -1;
for( int i = 0; i < n_coords; i++ ) for ( int i = 0; i < n_coords; i++ ) {
{
coords[i] = p_coords[i]; coords[i] = p_coords[i];
if ( min_x == -1 || coords[i].X() < min_x ) if ( min_x == -1 || coords[i].X() < min_x )
min_x = coords[i].X(); min_x = coords[i].X();
@ -79,38 +73,36 @@ Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords
calcCentre(); calcCentre();
} }
Polygon::Polygon( const Polygon &p_polygon ) : n_coords( p_polygon.n_coords ), extent( p_polygon.extent ), area( p_polygon.area ), centre( p_polygon.centre ) Polygon::Polygon( const Polygon &p_polygon ) :
n_coords(p_polygon.n_coords),
extent(p_polygon.extent),
area(p_polygon.area),
centre(p_polygon.centre)
{ {
coords = new Coord[n_coords]; coords = new Coord[n_coords];
for( int i = 0; i < n_coords; i++ ) for( int i = 0; i < n_coords; i++ ) {
{
coords[i] = p_polygon.coords[i]; coords[i] = p_polygon.coords[i];
} }
} }
Polygon &Polygon::operator=( const Polygon &p_polygon ) Polygon &Polygon::operator=( const Polygon &p_polygon ) {
{ if ( n_coords < p_polygon.n_coords ) {
if ( n_coords < p_polygon.n_coords )
{
delete[] coords; delete[] coords;
coords = new Coord[p_polygon.n_coords]; coords = new Coord[p_polygon.n_coords];
} }
n_coords = p_polygon.n_coords; n_coords = p_polygon.n_coords;
for( int i = 0; i < n_coords; i++ ) for ( int i = 0; i < n_coords; i++ ) {
{
coords[i] = p_polygon.coords[i]; coords[i] = p_polygon.coords[i];
} }
extent = p_polygon.extent; extent = p_polygon.extent;
area = p_polygon.area; area = p_polygon.area;
centre = p_polygon.centre; centre = p_polygon.centre;
return( *this ); return *this ;
} }
bool Polygon::isInside( const Coord &coord ) const bool Polygon::isInside( const Coord &coord ) const {
{
bool inside = false; bool inside = false;
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
{
if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) ) if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) )
|| ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y()))) || ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y())))
&& (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X())) && (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X()))
@ -118,5 +110,5 @@ bool Polygon::isInside( const Coord &coord ) const
inside = !inside; inside = !inside;
} }
} }
return( inside ); return inside;
} }

View File

@ -41,13 +41,13 @@ protected:
static int CompareYX( const void *p1, const void *p2 ) { static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2); const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
if ( e1->min_y == e2->min_y ) if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) ); return int(e1->min_x - e2->min_x);
else else
return( int(e1->min_y - e2->min_y) ); return int(e1->min_y - e2->min_y);
} }
static int CompareX( const void *p1, const void *p2 ) { static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2); const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
return( int(e1->min_x - e2->min_x) ); return int(e1->min_x - e2->min_x);
} }
}; };
@ -83,32 +83,32 @@ protected:
void calcCentre(); void calcCentre();
public: public:
inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ), edges(0), slices(0) { inline Polygon() : n_coords(0), coords(0), area(0), edges(0), slices(0) {
} }
Polygon( int p_n_coords, const Coord *p_coords ); Polygon(int p_n_coords, const Coord *p_coords);
Polygon( const Polygon &p_polygon ); Polygon(const Polygon &p_polygon);
~Polygon() { ~Polygon() {
delete[] coords; delete[] coords;
} }
Polygon &operator=( const Polygon &p_polygon ); Polygon &operator=( const Polygon &p_polygon );
inline int getNumCoords() const { return( n_coords ); } inline int getNumCoords() const { return n_coords; }
inline const Coord &getCoord( int index ) const { inline const Coord &getCoord( int index ) const {
return( coords[index] ); return coords[index];
} }
inline const Box &Extent() const { return( extent ); } inline const Box &Extent() const { return extent; }
inline int LoX() const { return( extent.LoX() ); } inline int LoX() const { return extent.LoX(); }
inline int HiX() const { return( extent.HiX() ); } inline int HiX() const { return extent.HiX(); }
inline int LoY() const { return( extent.LoY() ); } inline int LoY() const { return extent.LoY(); }
inline int HiY() const { return( extent.HiY() ); } inline int HiY() const { return extent.HiY(); }
inline int Width() const { return( extent.Width() ); } inline int Width() const { return extent.Width(); }
inline int Height() const { return( extent.Height() ); } inline int Height() const { return extent.Height(); }
inline int Area() const { return( area ); } inline int Area() const { return area; }
inline const Coord &Centre() const { inline const Coord &Centre() const {
return( centre ); return centre;
} }
bool isInside( const Coord &coord ) const; bool isInside( const Coord &coord ) const;
}; };

View File

@ -114,7 +114,7 @@ bool StreamBase::checkCommandQueue() {
return false; return false;
} }
Image *StreamBase::prepareImage( Image *image ) { Image *StreamBase::prepareImage(Image *image) {
// Do not bother to scale zoomed in images, just crop them and let the browser scale // Do not bother to scale zoomed in images, just crop them and let the browser scale
// Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream.
@ -124,51 +124,52 @@ Image *StreamBase::prepareImage( Image *image ) {
int mag = (scale * zoom) / ZM_SCALE_BASE; int mag = (scale * zoom) / ZM_SCALE_BASE;
int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag;
Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag );
int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE;
int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag;
Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag );
int base_image_width = image->Width(), base_image_height = image->Height(); int base_image_width = image->Width(), base_image_height = image->Height();
Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height );
int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE;
Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height );
int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE;
Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height );
int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE;
Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height );
int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE;
Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height );
int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE;
Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height );
int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE;
Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height );
int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag;
Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height );
int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag;
Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height );
if ( mag != ZM_SCALE_BASE ) { Debug(3,
if ( act_mag != ZM_SCALE_BASE ) { "Scaling by %d, zooming by %d = magnifying by %d(%d)\n"
"Last scaling by %d, zooming by %d = magnifying by %d(%d)\n"
"Base image width = %d, height = %d\n"
"Virtual image width = %d, height = %d\n"
"Last virtual image width = %d, height = %d\n"
"Actual image width = %d, height = %d\n"
"Last actual image width = %d, height = %d\n"
"Display image width = %d, height = %d\n"
"Last display image width = %d, height = %d\n"
"Send image width = %d, height = %d\n"
"Last send image width = %d, height = %d\n",
scale, zoom, mag, act_mag,
last_scale, last_zoom, last_mag, last_act_mag,
base_image_width, base_image_height,
virt_image_width, virt_image_height,
last_virt_image_width, last_virt_image_height,
act_image_width, act_image_height,
last_act_image_width, last_act_image_height,
disp_image_width, disp_image_height,
last_disp_image_width, last_disp_image_height,
send_image_width, send_image_height,
last_send_image_width, last_send_image_height
);
if ( ( mag != ZM_SCALE_BASE ) && (act_mag != ZM_SCALE_BASE) ) {
Debug(3, "Magnifying by %d", mag); Debug(3, "Magnifying by %d", mag);
if ( !image_copied ) {
static Image copy_image; static Image copy_image;
copy_image.Assign(*image); copy_image.Assign(*image);
image = &copy_image; image = &copy_image;
image_copied = true; image_copied = true;
}
image->Scale(mag); image->Scale(mag);
} }
}
Debug(3, "Real image width = %d, height = %d", image->Width(), image->Height()); Debug(3, "Real image width = %d, height = %d", image->Width(), image->Height());
@ -176,26 +177,22 @@ Image *StreamBase::prepareImage( Image *image ) {
static Box last_crop; static Box last_crop;
if ( mag != last_mag || x != last_x || y != last_y ) { if ( mag != last_mag || x != last_x || y != last_y ) {
Debug( 3, "Got click at %d,%d x %d", x, y, mag ); Debug(3, "Got click at %d,%d x %d", x, y, mag);
//if ( !last_mag )
//last_mag = mag;
if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) )
last_crop = Box(); last_crop = Box();
Debug( 3, "Recalculating crop" );
// Recalculate crop parameters, as %ges // Recalculate crop parameters, as %ges
int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image
click_x += ( x * 100 ) / last_virt_image_width; click_x += ( x * 100 ) / last_virt_image_width;
int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image
click_y += ( y * 100 ) / last_virt_image_height; click_y += ( y * 100 ) / last_virt_image_height;
Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); Debug(3, "Got adjusted click at %d%%,%d%%", click_x, click_y);
// Convert the click locations to the current image pixels // Convert the click locations to the current image pixels
click_x = ( click_x * act_image_width ) / 100; click_x = ( click_x * act_image_width ) / 100;
click_y = ( click_y * act_image_height ) / 100; click_y = ( click_y * act_image_height ) / 100;
Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); Debug(3, "Got readjusted click at %d,%d", click_x, click_y);
int lo_x = click_x - (send_image_width/2); int lo_x = click_x - (send_image_width/2);
if ( lo_x < 0 ) if ( lo_x < 0 )
@ -214,23 +211,25 @@ Image *StreamBase::prepareImage( Image *image ) {
lo_y = hi_y - (send_image_height - 1); lo_y = hi_y - (send_image_height - 1);
} }
last_crop = Box( lo_x, lo_y, hi_x, hi_y ); last_crop = Box( lo_x, lo_y, hi_x, hi_y );
} } // end if ( mag != last_mag || x != last_x || y != last_y )
Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() );
Debug(3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY());
if ( !image_copied ) { if ( !image_copied ) {
static Image copy_image; static Image copy_image;
copy_image.Assign( *image ); copy_image.Assign(*image);
image = &copy_image; image = &copy_image;
image_copied = true; image_copied = true;
} }
image->Crop( last_crop ); image->Crop(last_crop);
} } // end if difference in image vs displayed dimensions
last_scale = scale; last_scale = scale;
last_zoom = zoom; last_zoom = zoom;
last_x = x; last_x = x;
last_y = y; last_y = y;
return image; return image;
} } // end Image *StreamBase::prepareImage(Image *image)
bool StreamBase::sendTextFrame(const char *frame_text) { bool StreamBase::sendTextFrame(const char *frame_text) {
Debug(2, "Sending %dx%d * %d text frame '%s'", Debug(2, "Sending %dx%d * %d text frame '%s'",
@ -349,7 +348,7 @@ void StreamBase::openComms() {
} }
snprintf(rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", staticConfig.PATH_SOCKS.c_str(), connkey); snprintf(rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", staticConfig.PATH_SOCKS.c_str(), connkey);
strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path)-1); strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path));
rem_addr.sun_family = AF_UNIX; rem_addr.sun_family = AF_UNIX;
gettimeofday(&last_comm_update, NULL); gettimeofday(&last_comm_update, NULL);

View File

@ -77,11 +77,11 @@ protected:
protected: protected:
int connkey; int connkey;
int sd; int sd;
char loc_sock_path[PATH_MAX]; char loc_sock_path[108];
struct sockaddr_un loc_addr; struct sockaddr_un loc_addr;
char rem_sock_path[PATH_MAX]; char rem_sock_path[108];
struct sockaddr_un rem_addr; struct sockaddr_un rem_addr;
char sock_path_lock[PATH_MAX]; char sock_path_lock[108];
int lock_fd; int lock_fd;
protected: protected:

View File

@ -26,6 +26,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <utility>
#if HAVE_GNUTLS_GNUTLS_H #if HAVE_GNUTLS_GNUTLS_H
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
@ -35,7 +36,7 @@
#include <gcrypt.h> #include <gcrypt.h>
#elif HAVE_LIBCRYPTO #elif HAVE_LIBCRYPTO
#include <openssl/md5.h> #include <openssl/md5.h>
#endif // HAVE_L || HAVE_LIBCRYPTO #endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
#include "zm_utils.h" #include "zm_utils.h"
#include "zm_crypt.h" #include "zm_crypt.h"
@ -52,7 +53,7 @@ User::User(const MYSQL_ROW &dbrow) {
id = atoi(dbrow[index++]); id = atoi(dbrow[index++]);
strncpy(username, dbrow[index++], sizeof(username)-1); strncpy(username, dbrow[index++], sizeof(username)-1);
strncpy(password, dbrow[index++], sizeof(password)-1); strncpy(password, dbrow[index++], sizeof(password)-1);
enabled = (bool)atoi(dbrow[index++]); enabled = static_cast<bool>(atoi(dbrow[index++]));
stream = (Permission)atoi(dbrow[index++]); stream = (Permission)atoi(dbrow[index++]);
events = (Permission)atoi(dbrow[index++]); events = (Permission)atoi(dbrow[index++]);
control = (Permission)atoi(dbrow[index++]); control = (Permission)atoi(dbrow[index++]);
@ -61,7 +62,7 @@ User::User(const MYSQL_ROW &dbrow) {
char *monitor_ids_str = dbrow[index++]; char *monitor_ids_str = dbrow[index++];
if ( monitor_ids_str && *monitor_ids_str ) { if ( monitor_ids_str && *monitor_ids_str ) {
StringVector ids = split(monitor_ids_str, ","); StringVector ids = split(monitor_ids_str, ",");
for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) { for ( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
monitor_ids.push_back(atoi((*i).c_str())); monitor_ids.push_back(atoi((*i).c_str()));
} }
} }
@ -72,9 +73,9 @@ User::~User() {
} }
void User::Copy(const User &u) { void User::Copy(const User &u) {
id=u.id; id = u.id;
strncpy(username, u.username, sizeof(username)-1); strncpy(username, u.username, sizeof(username));
strncpy(password, u.password, sizeof(password)-1); strncpy(password, u.password, sizeof(password));
enabled = u.enabled; enabled = u.enabled;
stream = u.stream; stream = u.stream;
events = u.events; events = u.events;
@ -88,7 +89,8 @@ bool User::canAccess(int monitor_id) {
if ( monitor_ids.empty() ) if ( monitor_ids.empty() )
return true; return true;
for ( std::vector<int>::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) { for ( std::vector<int>::iterator i = monitor_ids.begin();
i != monitor_ids.end(); ++i ) {
if ( *i == monitor_id ) { if ( *i == monitor_id ) {
return true; return true;
} }
@ -103,18 +105,23 @@ User *zmLoadUser(const char *username, const char *password) {
int username_length = strlen(username); int username_length = strlen(username);
char *safer_username = new char[(username_length * 2) + 1]; char *safer_username = new char[(username_length * 2) + 1];
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator. // According to docs, size of safer_whatever must be 2*length+1
// due to unicode conversions + null terminator.
mysql_real_escape_string(&dbconn, safer_username, username, username_length); mysql_real_escape_string(&dbconn, safer_username, username, username_length);
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`" "SELECT `Id`, `Username`, `Password`, `Enabled`,"
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", safer_username); " `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0,"
" `MonitorIds`"
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1",
safer_username);
delete[] safer_username;
safer_username = NULL;
if ( mysql_query(&dbconn, sql) ) { if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn)); Error("Can't run query: %s", mysql_error(&dbconn));
exit(mysql_errno(&dbconn)); exit(mysql_errno(&dbconn));
} }
delete safer_username;
MYSQL_RES *result = mysql_store_result(&dbconn); MYSQL_RES *result = mysql_store_result(&dbconn);
if ( !result ) { if ( !result ) {
@ -122,68 +129,67 @@ User *zmLoadUser(const char *username, const char *password) {
exit(mysql_errno(&dbconn)); exit(mysql_errno(&dbconn));
} }
if ( mysql_num_rows(result) != 1 ) { if ( mysql_num_rows(result) == 1 ) {
mysql_free_result(result);
Warning("Unable to authenticate user %s", username);
return NULL;
}
MYSQL_ROW dbrow = mysql_fetch_row(result); MYSQL_ROW dbrow = mysql_fetch_row(result);
User *user = new User(dbrow); User *user = new User(dbrow);
mysql_free_result(result); mysql_free_result(result);
if ( !password ) { if (
// relay type must be none (! password ) // relay type must be none
return user; ||
} verifyPassword(username, password, user->getPassword()) ) {
if ( verifyPassword(username, password, user->getPassword()) ) {
Info("Authenticated user '%s'", user->getUsername()); Info("Authenticated user '%s'", user->getUsername());
return user; return user;
} }
} // end if 1 result from db
mysql_free_result(result);
Warning("Unable to authenticate user %s", username); Warning("Unable to authenticate user %s", username);
return NULL; return NULL;
} } // end User *zmLoadUser(const char *username, const char *password)
User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) { User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr) {
std::string key = config.auth_hash_secret; std::string key = config.auth_hash_secret;
std::string remote_addr = ""; std::string remote_addr = "";
if (use_remote_addr) { if ( use_remote_addr ) {
remote_addr = std::string(getenv( "REMOTE_ADDR" )); remote_addr = std::string(getenv("REMOTE_ADDR"));
if ( remote_addr == "" ) { if ( remote_addr == "" ) {
Warning( "Can't determine remote address, using null" ); Warning("Can't determine remote address, using null");
remote_addr = ""; remote_addr = "";
} }
key += remote_addr; key += remote_addr;
} }
Debug (1,"Inside zmLoadTokenUser, formed key=%s", key.c_str()); Debug(1, "Inside zmLoadTokenUser, formed key=%s", key.c_str());
std::pair<std::string, unsigned int> ans = verifyToken(jwt_token_str, key); std::pair<std::string, unsigned int> ans = verifyToken(jwt_token_str, key);
std::string username = ans.first; std::string username = ans.first;
unsigned int iat = ans.second; unsigned int iat = ans.second;
Debug (1,"retrieved user '%s' from token", username.c_str()); Debug(1, "retrieved user '%s' from token", username.c_str());
if ( username == "" ) {
return NULL;
}
if (username != "") {
char sql[ZM_SQL_MED_BUFSIZ] = ""; char sql[ZM_SQL_MED_BUFSIZ] = "";
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`" "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0,"
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str() ); " `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`"
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str());
if ( mysql_query(&dbconn, sql) ) { if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn)); Error("Can't run query: %s", mysql_error(&dbconn));
exit(mysql_errno(&dbconn)); return NULL;
} }
MYSQL_RES *result = mysql_store_result(&dbconn); MYSQL_RES *result = mysql_store_result(&dbconn);
if ( !result ) { if ( !result ) {
Error("Can't use query result: %s", mysql_error(&dbconn)); Error("Can't use query result: %s", mysql_error(&dbconn));
exit(mysql_errno(&dbconn)); return NULL;
} }
int n_users = mysql_num_rows(result);
int n_users = mysql_num_rows(result);
if ( n_users != 1 ) { if ( n_users != 1 ) {
mysql_free_result(result); mysql_free_result(result);
Error("Unable to authenticate user '%s'", username.c_str()); Error("Unable to authenticate user '%s'", username.c_str());
@ -192,92 +198,88 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
MYSQL_ROW dbrow = mysql_fetch_row(result); MYSQL_ROW dbrow = mysql_fetch_row(result);
User *user = new User(dbrow); User *user = new User(dbrow);
unsigned int stored_iat = strtoul(dbrow[10], NULL,0 ); unsigned int stored_iat = strtoul(dbrow[10], NULL, 0);
if (stored_iat > iat ) { // admin revoked tokens if ( stored_iat > iat ) { // admin revoked tokens
mysql_free_result(result); mysql_free_result(result);
Error("Token was revoked for '%s'", username.c_str()); Error("Token was revoked for '%s'", username.c_str());
return NULL; return NULL;
} }
Debug (1,"Got last token revoke time of: %u",stored_iat); Debug(1, "Authenticated user '%s' via token with last revoke time: %u",
Debug (1,"Authenticated user '%s' via token", username.c_str()); username.c_str(), stored_iat);
mysql_free_result(result); mysql_free_result(result);
return user; return user;
} // User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr)
}
else {
return NULL;
}
}
// Function to validate an authentication string // Function to validate an authentication string
User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { User *zmLoadAuthUser(const char *auth, bool use_remote_addr) {
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
#ifdef HAVE_GCRYPT_H #ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt // Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) ) { if ( !gcry_check_version(GCRYPT_VERSION) ) {
Fatal( "Unable to initialise libgcrypt" ); Fatal("Unable to initialise libgcrypt");
} }
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
#endif // HAVE_GCRYPT_H #endif // HAVE_GCRYPT_H
const char *remote_addr = ""; const char *remote_addr = "";
if ( use_remote_addr ) { if ( use_remote_addr ) {
remote_addr = getenv( "REMOTE_ADDR" ); remote_addr = getenv("REMOTE_ADDR");
if ( !remote_addr ) { if ( !remote_addr ) {
Warning( "Can't determine remote address, using null" ); Warning("Can't determine remote address, using null");
remote_addr = ""; remote_addr = "";
} }
} }
Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); Debug(1, "Attempting to authenticate user from auth string '%s'", auth);
char sql[ZM_SQL_SML_BUFSIZ] = ""; char sql[ZM_SQL_SML_BUFSIZ] = "";
snprintf( sql, sizeof(sql), "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds` FROM `Users` WHERE `Enabled` = 1" ); snprintf(sql, sizeof(sql),
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
" `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0,"
" `MonitorIds` FROM `Users` WHERE `Enabled` = 1");
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query(&dbconn, sql) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error("Can't run query: %s", mysql_error(&dbconn));
exit( mysql_errno( &dbconn ) ); exit(mysql_errno(&dbconn));
} }
MYSQL_RES *result = mysql_store_result( &dbconn ); MYSQL_RES *result = mysql_store_result(&dbconn);
if ( !result ) { if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error("Can't use query result: %s", mysql_error(&dbconn));
exit( mysql_errno( &dbconn ) ); return NULL;
} }
int n_users = mysql_num_rows( result ); int n_users = mysql_num_rows(result);
if ( n_users < 1 ) { if ( n_users < 1 ) {
mysql_free_result( result ); mysql_free_result(result);
Warning( "Unable to authenticate user" ); Warning("Unable to authenticate user");
return( 0 ); return NULL;
} }
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) { time_t now = time(0);
const char *user = dbrow[1]; unsigned int hours = config.auth_hash_ttl;
const char *pass = dbrow[2]; if ( ! hours ) {
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
hours = 2;
} else {
Debug(1, "AUTH_HASH_TTL is %d", hours);
}
char auth_key[512] = ""; char auth_key[512] = "";
char auth_md5[32+1] = ""; char auth_md5[32+1] = "";
size_t md5len = 16; size_t md5len = 16;
unsigned char md5sum[md5len]; unsigned char md5sum[md5len];
time_t now = time( 0 ); const char * hex = "0123456789abcdef";
unsigned int hours = config.auth_hash_ttl; while ( MYSQL_ROW dbrow = mysql_fetch_row(result) ) {
const char *user = dbrow[1];
const char *pass = dbrow[2];
if ( ! hours ) { time_t our_now = now;
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2."); for ( unsigned int i = 0; i < hours; i++, our_now -= 3600 ) {
hours = 2; struct tm *now_tm = localtime(&our_now);
} else {
Debug( 1, "AUTH_HASH_TTL is %d", hours );
}
for ( unsigned int i = 0; i < hours; i++, now -= 3600 ) { snprintf(auth_key, sizeof(auth_key)-1, "%s%s%s%s%d%d%d%d",
struct tm *now_tm = localtime( &now );
snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
config.auth_hash_secret, config.auth_hash_secret,
user, user,
pass, pass,
@ -285,51 +287,57 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
now_tm->tm_hour, now_tm->tm_hour,
now_tm->tm_mday, now_tm->tm_mday,
now_tm->tm_mon, now_tm->tm_mon,
now_tm->tm_year now_tm->tm_year);
);
#if HAVE_DECL_MD5 #if HAVE_DECL_MD5
MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); MD5((unsigned char *)auth_key, strlen(auth_key), md5sum);
#elif HAVE_DECL_GNUTLS_FINGERPRINT #elif HAVE_DECL_GNUTLS_FINGERPRINT
gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; gnutls_datum_t md5data = { (unsigned char *)auth_key, (unsigned int)strlen(auth_key) };
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); gnutls_fingerprint(GNUTLS_DIG_MD5, &md5data, md5sum, &md5len);
#endif #endif
auth_md5[0] = '\0'; unsigned char *md5sum_ptr = md5sum;
char *auth_md5_ptr = auth_md5;
for ( unsigned int j = 0; j < md5len; j++ ) { for ( unsigned int j = 0; j < md5len; j++ ) {
sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); *auth_md5_ptr++ = hex[(*md5sum_ptr>>4)&0xf];
*auth_md5_ptr++ = hex[(*md5sum_ptr++)&0xf];
} }
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth ); *auth_md5_ptr = 0;
if ( !strcmp( auth, auth_md5 ) ) { Debug(1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'",
auth_key, auth_md5, auth);
if ( !strcmp(auth, auth_md5) ) {
// We have a match // We have a match
User *user = new User( dbrow ); User *user = new User(dbrow);
Debug(1, "Authenticated user '%s'", user->getUsername() ); Debug(1, "Authenticated user '%s'", user->getUsername());
mysql_free_result( result ); mysql_free_result(result);
return( user ); return user;
} else { } else {
Debug(1, "No match for %s", auth ); Debug(1, "No match for %s", auth);
} }
} } // end foreach hour
} } // end foreach user
mysql_free_result( result ); mysql_free_result(result);
#else // HAVE_DECL_MD5 #else // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); Error("You need to build with gnutls or openssl to use hash based auth");
#endif // HAVE_DECL_MD5 #endif // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
Debug(1, "No user found for auth_key %s", auth ); Debug(1, "No user found for auth_key %s", auth);
return 0; return NULL;
} } // end User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
//Function to check Username length // Function to check Username length
bool checkUser ( const char *username) { bool checkUser(const char *username) {
if ( ! username ) if ( !username )
return false; return false;
if ( strlen(username) > 32 ) if ( strlen(username) > 32 )
return false; return false;
return true; return true;
} }
//Function to check password length
bool checkPass (const char *password) { // Function to check password length
bool checkPass(const char *password) {
if ( !password ) if ( !password )
return false; return false;
if ( strlen(password) > 64 ) if ( strlen(password) > 64 )

View File

@ -184,7 +184,7 @@ int main(int argc, const char *argv[]) {
logInit(log_id_string); logInit(log_id_string);
if ( config.opt_use_auth ) { if ( config.opt_use_auth ) {
User *user = 0; User *user = NULL;
if ( jwt_token_str != "" ) { if ( jwt_token_str != "" ) {
// user = zmLoadTokenUser(jwt_token_str, config.auth_hash_ips); // user = zmLoadTokenUser(jwt_token_str, config.auth_hash_ips);
@ -195,21 +195,13 @@ int main(int argc, const char *argv[]) {
} else { } else {
Error("Bad username"); Error("Bad username");
} }
} else { } else {
// if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{
if ( *auth ) { if ( *auth ) {
user = zmLoadAuthUser(auth, config.auth_hash_ips); user = zmLoadAuthUser(auth, config.auth_hash_ips);
} } else if ( username.length() && password.length() ) {
}
// else if ( strcmp( config.auth_relay, "plain" ) == 0 )
{
if ( username.length() && password.length() ) {
user = zmLoadUser(username.c_str(), password.c_str()); user = zmLoadUser(username.c_str(), password.c_str());
} }
} }
}
if ( !user ) { if ( !user ) {
fputs("HTTP/1.0 403 Forbidden\r\n\r\n", stdout); fputs("HTTP/1.0 403 Forbidden\r\n\r\n", stdout);
Error("Unable to authenticate user"); Error("Unable to authenticate user");
@ -218,11 +210,15 @@ int main(int argc, const char *argv[]) {
return 0; return 0;
} }
if ( !ValidateAccess(user, monitor_id) ) { if ( !ValidateAccess(user, monitor_id) ) {
delete user;
user = NULL;
fputs("HTTP/1.0 403 Forbidden\r\n\r\n", stdout); fputs("HTTP/1.0 403 Forbidden\r\n\r\n", stdout);
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return 0; return 0;
} }
delete user;
user = NULL;
} // end if config.opt_use_auth } // end if config.opt_use_auth
hwcaps_detect(); hwcaps_detect();
@ -336,5 +332,5 @@ int main(int argc, const char *argv[]) {
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return(0); return 0;
} }

View File

@ -1 +1 @@
1.34.10 1.34.11

View File

@ -39,7 +39,7 @@ class Monitor extends ZM_Object {
'Height' => null, 'Height' => null,
'Colours' => 4, 'Colours' => 4,
'Palette' => '0', 'Palette' => '0',
'Orientation' => null, 'Orientation' => 'ROTATE_0',
'Deinterlacing' => 0, 'Deinterlacing' => 0,
'DecoderHWAccelName' => null, 'DecoderHWAccelName' => null,
'DecoderHWAccelDevice' => null, 'DecoderHWAccelDevice' => null,
@ -495,12 +495,16 @@ class Monitor extends ZM_Object {
} }
} }
if ( !count($options) ) { if ( !count($options) ) {
if ( $command == 'quit' ) {
$options['command'] = 'quit'; if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
} else if ( $command == 'start' ) { # These are special as we now run zmcontrol as a daemon through zmdc.
$options['command'] = 'start'; $status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
} else if ( $command == 'stop' ) { Logger::Debug("Current status $status");
$options['command'] = 'stop'; if ( $status or ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) ) {
daemonControl($command, 'zmcontrol.pl', '--id '.$this->{'Id'});
return;
}
$options['command'] = $command;
} else { } else {
Warning("No commands to send to zmcontrol from $command"); Warning("No commands to send to zmcontrol from $command");
return false; return false;
@ -538,12 +542,12 @@ class Monitor extends ZM_Object {
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json'; $url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
if ( ZM_OPT_USE_AUTH ) { if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) { if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); $url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
} else if ( ZM_AUTH_RELAY == 'plain' ) { } else if ( ZM_AUTH_RELAY == 'plain' ) {
$url = '?user='.$_SESSION['username']; $url .= '?user='.$_SESSION['username'];
$url = '?pass='.$_SESSION['password']; $url .= '?pass='.$_SESSION['password'];
} else if ( ZM_AUTH_RELAY == 'none' ) { } else if ( ZM_AUTH_RELAY == 'none' ) {
$url = '?user='.$_SESSION['username']; $url .= '?user='.$_SESSION['username'];
} }
} }
Logger::Debug("sending command to $url"); Logger::Debug("sending command to $url");

View File

@ -249,7 +249,7 @@ class ZM_Object {
} }
} }
} else if ( array_key_exists($field, $this->defaults) ) { } else if ( array_key_exists($field, $this->defaults) ) {
if ( is_array($this->defaults[$field]) ) { if ( is_array($this->defaults[$field]) and isset($this->defaults[$field]['default']) ) {
$default = $this->defaults[$field]['default']; $default = $this->defaults[$field]['default'];
} else { } else {
$default = $this->defaults[$field]; $default = $this->defaults[$field];

41
web/includes/Zone.php Normal file
View File

@ -0,0 +1,41 @@
<?php
namespace ZM;
require_once('database.php');
require_once('Object.php');
class Zone extends ZM_Object {
protected static $table = 'Zones';
protected $defaults = array(
'Id' => null,
'Name' => '',
'Type' => 'Active',
'Units' => 'Pixels',
'CheckMethod' => 'Blobs',
'MinPixelThreshold' => null,
'MaxPixelThreshold' => null,
'MinAlarmPixels' => null,
'MaxAlarmPixels' => null,
'FilterX' => null,
'FilterY' => null,
'MinFilterPixels' => null,
'MaxFilterPixels' => null,
'MinBlobPixels' => null,
'MaxBlobPixels' => null,
'MinBlobs' => null,
'MaxBlobs' => null,
'OverloadFrames' => 0,
'ExtendAlarmFrames' => 0,
);
public static function find( $parameters = array(), $options = array() ) {
return ZM_Object::_find(get_class(), $parameters, $options);
}
public static function find_one( $parameters = array(), $options = array() ) {
return ZM_Object::_find_one(get_class(), $parameters, $options);
}
} # end class Zone
?>

View File

@ -52,6 +52,9 @@ require_once('includes/Event.php');
require_once('includes/Group.php'); require_once('includes/Group.php');
require_once('includes/Monitor.php'); require_once('includes/Monitor.php');
global $Servers;
$Servers = ZM\Server::find();
if ( if (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
or or
@ -71,7 +74,7 @@ define('ZM_BASE_URL', '');
require_once('includes/functions.php'); require_once('includes/functions.php');
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) { if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
ZM\Logger::Debug("OPTIONS Method, only doing CORS"); ZM\Logger::Debug('OPTIONS Method, only doing CORS');
# Add Cross domain access headers # Add Cross domain access headers
CORSHeaders(); CORSHeaders();
return; return;
@ -152,8 +155,6 @@ if (
setcookie('zmCSS', $css, time()+3600*24*30*12*10); setcookie('zmCSS', $css, time()+3600*24*30*12*10);
} }
# Running is global but only do the daemonCheck if it is actually needed # Running is global but only do the daemonCheck if it is actually needed
$running = null; $running = null;
@ -174,7 +175,6 @@ $user = null;
if ( isset($_REQUEST['view']) ) if ( isset($_REQUEST['view']) )
$view = detaintPath($_REQUEST['view']); $view = detaintPath($_REQUEST['view']);
# Add CSP Headers # Add CSP Headers
$cspNonce = bin2hex(zm_random_bytes(16)); $cspNonce = bin2hex(zm_random_bytes(16));

View File

@ -25,15 +25,15 @@ function controlFocus($monitor, $cmds) {
?> ?>
<div class="arrowControl focusControls"> <div class="arrowControl focusControls">
<div class="arrowLabel"><?php echo translate('Near') ?></div> <div class="arrowLabel"><?php echo translate('Near') ?></div>
<button type="button" class="longArrowBtn upBtn" value="<?php echo $cmds['FocusNear'] ?>" data-on-click-this="controlCmd" data-xtell="0" data-ytell="-1"></button> <button type="button" class="longArrowBtn upBtn" value="<?php echo $cmds['FocusNear'] ?>" data-on-click="controlCmd" data-xtell="0" data-ytell="-1"></button>
<button type="button" class="arrowCenter"<?php if ( $control->CanFocusCon() ) { ?> data-on-click-this="controlCmd" value="<?php echo $cmds['FocusStop'] ?>"<?php } ?>><?php echo translate('Focus') ?></button> <button type="button" class="arrowCenter"<?php if ( $control->CanFocusCon() ) { ?> data-on-click="controlCmd" value="<?php echo $cmds['FocusStop'] ?>"<?php } ?>><?php echo translate('Focus') ?></button>
<button type="button" class="longArrowBtn downBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['FocusFar'] ?>" data-xtell="0" data-ytell="1"></button> <button type="button" class="longArrowBtn downBtn" data-on-click="controlCmd" value="<?php echo $cmds['FocusFar'] ?>" data-xtell="0" data-ytell="1"></button>
<div class="arrowLabel"><?php echo translate('Far') ?></div> <div class="arrowLabel"><?php echo translate('Far') ?></div>
<?php <?php
if ( $control->CanAutoFocus() ) { if ( $control->CanAutoFocus() ) {
?> ?>
<button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusAuto'] ?>" data-on-click-this="controlCmd"><?php echo translate('Auto') ?></button> <button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusAuto'] ?>" data-on-click="controlCmd"><?php echo translate('Auto') ?></button>
<button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusMan'] ?>" data-on-click-this="controlCmd"><?php echo translate('Man') ?></button> <button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusMan'] ?>" data-on-click="controlCmd"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -48,15 +48,15 @@ function controlZoom($monitor, $cmds) {
?> ?>
<div class="arrowControl zoomControls"> <div class="arrowControl zoomControls">
<div class="arrowLabel"><?php echo translate('Tele') ?></div> <div class="arrowLabel"><?php echo translate('Tele') ?></div>
<button type="button" class="longArrowBtn upBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['ZoomTele'] ?>" data-xtell="0" data-ytell="-1"></button> <button type="button" class="longArrowBtn upBtn" data-on-click="controlCmd" value="<?php echo $cmds['ZoomTele'] ?>" data-xtell="0" data-ytell="-1"></button>
<button type="button" class="arrowCenter"<?php if ( $control->CanZoomCon() ) { ?> data-on-click-this="controlCmd" value="<?php echo $cmds['ZoomStop'] ?>"<?php } ?>><?php echo translate('Zoom') ?></button> <button type="button" class="arrowCenter"<?php if ( $control->CanZoomCon() ) { ?> data-on-click="controlCmd" value="<?php echo $cmds['ZoomStop'] ?>"<?php } ?>><?php echo translate('Zoom') ?></button>
<button type="button" class="longArrowBtn downBtn" data-on-click-data="controlCmd" value="<?php echo $cmds['ZoomWide'] ?>" data-xtell="0" data-ytell="1"></button> <button type="button" class="longArrowBtn downBtn" data-on-click="controlCmd" value="<?php echo $cmds['ZoomWide'] ?>" data-xtell="0" data-ytell="1"></button>
<div class="arrowLabel"><?php echo translate('Wide') ?></div> <div class="arrowLabel"><?php echo translate('Wide') ?></div>
<?php <?php
if ( $control->CanAutoZoom() ) { if ( $control->CanAutoZoom() ) {
?> ?>
<button type="button" class="ptzTextBtn" value="Auto" data-on-click-this="controlCmd" value="<?php echo $cmds['ZoomAuto'] ?>"><?php echo translate('Auto') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['ZoomAuto'] ?>"><?php echo translate('Auto') ?></button>
<button type="button" class="ptzTextBtn" value="Man" data-on-click-this="controlCmd" value="<?php echo $cmds['ZoomMan'] ?>"><?php echo translate('Man') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['ZoomMan'] ?>"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -70,15 +70,15 @@ function controlIris($monitor, $cmds) {
?> ?>
<div class="arrowControl irisControls"> <div class="arrowControl irisControls">
<div class="arrowLabel"><?php echo translate('Open') ?></div> <div class="arrowLabel"><?php echo translate('Open') ?></div>
<button type="button" class="longArrowBtn upBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['IrisOpen'] ?>" data-xtell="0" data-ytell="-1"></button> <button type="button" class="longArrowBtn upBtn" data-on-click="controlCmd" value="<?php echo $cmds['IrisOpen'] ?>" data-xtell="0" data-ytell="-1"></button>
<button type="button" class="arrowCenter"<?php if ( $control->CanIrisCon() ) { ?> data-on-click-this="controlCmd" value="<?php echo $cmds['IrisStop'] ?>"<?php } ?>><?php echo translate('Iris') ?></button> <button type="button" class="arrowCenter"<?php if ( $control->CanIrisCon() ) { ?> data-on-click="controlCmd" value="<?php echo $cmds['IrisStop'] ?>"<?php } ?>><?php echo translate('Iris') ?></button>
<button type="button" class="longArrowBtn downBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['IrisClose'] ?>" data-xtell="0" data-ytell="1"></button> <button type="button" class="longArrowBtn downBtn" data-on-click="controlCmd" value="<?php echo $cmds['IrisClose'] ?>" data-xtell="0" data-ytell="1"></button>
<div class="arrowLabel"><?php echo translate('Close') ?></div> <div class="arrowLabel"><?php echo translate('Close') ?></div>
<?php <?php
if ( $control->CanAutoIris() ) { if ( $control->CanAutoIris() ) {
?> ?>
<button type="button" class="ptzTextBtn" value="Auto" data-on-click-this="controlCmd" value="<?php echo $cmds['IrisAuto'] ?>"><?php echo translate('Auto') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['IrisAuto'] ?>"><?php echo translate('Auto') ?></button>
<button type="button" class="ptzTextBtn" value="Man" data-on-click-this="controlCmd" value="<?php echo $cmds['IrisMan'] ?>"><?php echo translate('Man') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['IrisMan'] ?>"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -93,15 +93,15 @@ function controlWhite($monitor, $cmds) {
?> ?>
<div class="arrowControl whiteControls"> <div class="arrowControl whiteControls">
<div class="arrowLabel"><?php echo translate('In') ?></div> <div class="arrowLabel"><?php echo translate('In') ?></div>
<button type="button" class="longArrowBtn upBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['WhiteIn'] ?>" data-xtell="0" data-ytell="-1"></button> <button type="button" class="longArrowBtn upBtn" data-on-click="controlCmd" value="<?php echo $cmds['WhiteIn'] ?>" data-xtell="0" data-ytell="-1"></button>
<button type="button" class="arrowCenter"<?php if ( $control->CanWhiteCon() ) { ?> data-on-click-this="controlCmd" value="<?php echo $cmds['WhiteStop'] ?>"<?php } ?>><?php echo translate('White') ?></button> <button type="button" class="arrowCenter"<?php if ( $control->CanWhiteCon() ) { ?> data-on-click="controlCmd" value="<?php echo $cmds['WhiteStop'] ?>"<?php } ?>><?php echo translate('White') ?></button>
<button type="button" class="longArrowBtn downBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['WhiteOut'] ?>" data-xtell="0" data-ytell="1)"></button> <button type="button" class="longArrowBtn downBtn" data-on-click="controlCmd" value="<?php echo $cmds['WhiteOut'] ?>" data-xtell="0" data-ytell="1)"></button>
<div class="arrowLabel"><?php echo translate('Out') ?></div> <div class="arrowLabel"><?php echo translate('Out') ?></div>
<?php <?php
if ( $control->CanAutoWhite() ) { if ( $control->CanAutoWhite() ) {
?> ?>
<button type="button" class="ptzTextBtn" value="Auto" data-on-click-this="controlCmd" value="<?php echo $cmds['WhiteAuto'] ?>"><?php echo translate('Auto') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['WhiteAuto'] ?>"><?php echo translate('Auto') ?></button>
<button type="button" class="ptzTextBtn" value="Man" data-on-click-this="controlCmd" value="<?php echo $cmds['WhiteMan'] ?>"><?php echo translate('Man') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['WhiteMan'] ?>"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -122,19 +122,19 @@ function controlPanTilt($monitor, $cmds) {
$hasTilt = $control->CanTilt(); $hasTilt = $control->CanTilt();
$hasDiag = $hasPan && $hasTilt && $control->CanMoveDiag(); $hasDiag = $hasPan && $hasTilt && $control->CanMoveDiag();
?> ?>
<button type="button" class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveUpLeft'] ?>" data-xtell="-1" data-ytell="-1"></button> <button type="button" class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveUpLeft'] ?>" data-xtell="-1" data-ytell="-1"></button>
<button type="button" class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveUp'] ?>" data-xtell="0" data-ytell="-1"></button> <button type="button" class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveUp'] ?>" data-xtell="0" data-ytell="-1"></button>
<button type="button" class="arrowBtn upRightBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveUpRight'] ?>" data-xtell="1" data-ytell="-1"></button> <button type="button" class="arrowBtn upRightBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveUpRight'] ?>" data-xtell="1" data-ytell="-1"></button>
<button type="button" class="arrowBtn leftBtn<?php echo $hasPan?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveLeft'] ?>" data-xtell="-1" data-ytell="0"></button> <button type="button" class="arrowBtn leftBtn<?php echo $hasPan?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveLeft'] ?>" data-xtell="-1" data-ytell="0"></button>
<?php if ( isset($cmds['Center']) ) { ?> <?php if ( isset($cmds['Center']) ) { ?>
<button type="button" class="arrowBtn centerBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['Center'] ?>"></button> <button type="button" class="arrowBtn centerBtn" data-on-click="controlCmd" value="<?php echo $cmds['Center'] ?>"></button>
<?php } else { ?> <?php } else { ?>
<button type="button" class="arrowBtn NocenterBtn"></button> <button type="button" class="arrowBtn NocenterBtn"></button>
<?php } ?> <?php } ?>
<button type="button" class="arrowBtn rightBtn<?php echo $hasPan?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveRight'] ?>" data-xtell="1" data-ytell="0"></button> <button type="button" class="arrowBtn rightBtn<?php echo $hasPan?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveRight'] ?>" data-xtell="1" data-ytell="0"></button>
<button type="button" class="arrowBtn downLeftBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveDownLeft'] ?>" data-xtell="-1" data-ytell="1"></button> <button type="button" class="arrowBtn downLeftBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveDownLeft'] ?>" data-xtell="-1" data-ytell="1"></button>
<button type="button" class="arrowBtn downBtn<?php echo $hasTilt?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveDown'] ?>" data-xtell="0" data-ytell="1"></button> <button type="button" class="arrowBtn downBtn<?php echo $hasTilt?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveDown'] ?>" data-xtell="0" data-ytell="1"></button>
<button type="button" class="arrowBtn downRightBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['MoveDownRight'] ?>" data-xtell="1" data-ytell="1"></button> <button type="button" class="arrowBtn downRightBtn<?php echo $hasDiag?'':' invisible' ?>" data-on-click="controlCmd" value="<?php echo $cmds['MoveDownRight'] ?>" data-xtell="1" data-ytell="1"></button>
</div> </div>
</div> </div>
<?php <?php
@ -162,7 +162,7 @@ function controlPresets($monitor, $cmds) {
<?php <?php
for ( $i = 1; $i <= $control->NumPresets(); $i++ ) { for ( $i = 1; $i <= $control->NumPresets(); $i++ ) {
?> ?>
<button type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?htmlentities($labels[$i]):'' ?>" value="<?php echo $i ?>" data-on-click-this="controlCmd" value="<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>"/><?php echo $i ?></button> <button type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?htmlentities($labels[$i]):'' ?>" data-on-click="controlCmd" value="<?php echo $cmds['PresetGoto'].$i ?>"/><?php echo $i ?></button>
<?php <?php
} // end foreach preset } // end foreach preset
?> ?>
@ -171,7 +171,7 @@ function controlPresets($monitor, $cmds) {
<?php <?php
if ( $control->HasHomePreset() ) { if ( $control->HasHomePreset() ) {
?> ?>
<button type="button" class="ptzTextBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['PresetHome'] ?>"><?php echo translate('Home') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['PresetHome'] ?>"><?php echo translate('Home') ?></button>
<?php <?php
} }
if ( canEdit('Monitors') && $control->CanSetPresets() ) { if ( canEdit('Monitors') && $control->CanSetPresets() ) {
@ -196,22 +196,22 @@ function controlPower($monitor, $cmds) {
<?php <?php
if ( $control->CanWake() ) { if ( $control->CanWake() ) {
?> ?>
<button type="button" class="ptzTextBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['Wake'] ?>"><?php echo translate('Wake') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['Wake'] ?>"><?php echo translate('Wake') ?></button>
<?php <?php
} }
if ( $control->CanSleep() ) { if ( $control->CanSleep() ) {
?> ?>
<button type="button" class="ptzTextBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['Sleep'] ?>"><?php echo translate('Sleep') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['Sleep'] ?>"><?php echo translate('Sleep') ?></button>
<?php <?php
} }
if ( $control->CanReset() ) { if ( $control->CanReset() ) {
?> ?>
<button type="button" class="ptzTextBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['Reset'] ?>"><?php echo translate('Reset') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['Reset'] ?>"><?php echo translate('Reset') ?></button>
<?php <?php
} }
if ( $control->CanReboot() ) { if ( $control->CanReboot() ) {
?> ?>
<button type="button" class="ptzTextBtn" data-on-click-this="controlCmd" value="<?php echo $cmds['Reboot'] ?>"><?php echo translate('Reboot') ?></button> <button type="button" class="ptzTextBtn" data-on-click="controlCmd" value="<?php echo $cmds['Reboot'] ?>"><?php echo translate('Reboot') ?></button>
<?php <?php
} }
?> ?>
@ -223,9 +223,7 @@ function controlPower($monitor, $cmds) {
function ptzControls($monitor) { function ptzControls($monitor) {
$control = $monitor->Control(); $control = $monitor->Control();
//ZM\Error("Control: " . print_r($control,true));
$cmds = $control->commands(); $cmds = $control->commands();
//ZM\Error("Cmds: " . print_r($cmds, true));
ob_start(); ob_start();
?> ?>
<div class="controlsPanel"> <div class="controlsPanel">

View File

@ -182,8 +182,8 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
return; return;
} }
el.onclick = function() { el.onclick = function(ev) {
window[fnName](); window[fnName](ev);
}; };
}); });

View File

@ -71,6 +71,22 @@ var focusWindow = <?php echo !empty($focusWindow)?'true':'false' ?>;
var imagePrefix = "<?php echo '?view=image&eid=' ?>"; var imagePrefix = "<?php echo '?view=image&eid=' ?>";
var auth_hash; var auth_hash;
<?php if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { ?> var auth_relay;
auth_hash = '<?php echo generateAuthHash(ZM_AUTH_HASH_IPS) ?>'; <?php
<?php } ?> if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
echo ' auth_hash = \''.generateAuthHash(ZM_AUTH_HASH_IPS).'\';
';
} else if ( ZM_AUTH_RELAY == 'plain' ) {
// password probably needs to be escaped
echo ' auth_relay=\'username='.$_SESSION['username'].'&password='.$_SESSION['password'].'\';
';
} else if ( ZM_AUTH_RELAY == 'none' ) {
// password probably needs to be escaped
echo ' auth_relay=\'username='.$_SESSION['username'].'\';
';
} else {
ZM\Error('Unknown value for ZM_AUTH_RELAY ' . ZM_AUTH_RELAY);
}
}
?>

View File

@ -258,7 +258,7 @@ while ( $event_row = dbFetchNext($results) ) {
echo '<td class="colThumbnail">'; echo '<td class="colThumbnail">';
$imgSrc = $event->getThumbnailSrc(array(),'&amp;'); $imgSrc = $event->getThumbnailSrc(array(),'&amp;');
$streamSrc = $event->getStreamSrc(array( $streamSrc = $event->getStreamSrc(array(
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single'), '&amp;'); 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
$imgHtml = '<img id="thumbnail'.$event->Id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($event->ThumbnailWidth()) .'px;height:'. validInt($event->ThumbnailHeight()).'px;" stream_src="'.$streamSrc.'" still_src="'.$imgSrc.'"/>'; $imgHtml = '<img id="thumbnail'.$event->Id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($event->ThumbnailWidth()) .'px;height:'. validInt($event->ThumbnailHeight()).'px;" stream_src="'.$streamSrc.'" still_src="'.$imgSrc.'"/>';
echo '<a href="?view=event&amp;eid='. $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$imgHtml.'</a>'; echo '<a href="?view=event&amp;eid='. $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$imgHtml.'</a>';

View File

@ -13,6 +13,8 @@ function Monitor(monitorData) {
this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey; this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey;
if ( auth_hash ) { if ( auth_hash ) {
this.streamCmdParms += '&auth='+auth_hash; this.streamCmdParms += '&auth='+auth_hash;
} else if ( auth_relay ) {
this.streamCmdParms += '&'+auth_relay;
} }
this.streamCmdTimer = null; this.streamCmdTimer = null;
this.type = monitorData.type; this.type = monitorData.type;

View File

@ -21,13 +21,13 @@
} }
?>'; ?>';
if ( querySuffix == '?view=login' ) { if ( querySuffix == '?view=login' || querySuffix == '' ) {
// If we didn't redirect elsewhere, then don't show login page, go to console // If we didn't redirect elsewhere, then don't show login page, go to console
querySuffix = '?view=console'; querySuffix = '?view=console';
} }
var newUrl = querySuffix; var newUrl = querySuffix;
console.log("Current location: " + window.location);
console.log("Redirecting to" + newUrl + ' ' + thisUrl); console.log("Redirecting to (" + newUrl + ') from :' + thisUrl);
window.location.replace(newUrl); window.location.replace(newUrl);
} }
).delay( 500 ); ).delay( 500 );

View File

@ -546,42 +546,62 @@ function getEventCmdResponse( respObj, respText ) {
} ); } );
for ( var i = 0; i < dbEvents.length; i++ ) { for ( var i = 0; i < dbEvents.length; i++ ) {
var event = dbEvents[i]; var zm_event = dbEvents[i];
var row = $('event'+event.Id); var row = $('event'+zm_event.Id);
var newEvent = (row == null ? true : false); var newEvent = (row == null ? true : false);
if ( newEvent ) { if ( newEvent ) {
row = new Element( 'tr', {'id': 'event'+event.Id} ); row = new Element('tr', {'id': 'event'+zm_event.Id});
new Element( 'td', {'class': 'colId'} ).inject( row ); new Element('td', {'class': 'colId'}).inject(row);
new Element( 'td', {'class': 'colName'} ).inject( row ); new Element('td', {'class': 'colName'}).inject(row);
new Element( 'td', {'class': 'colTime'} ).inject( row ); new Element('td', {'class': 'colTime'}).inject(row);
new Element( 'td', {'class': 'colSecs'} ).inject( row ); new Element('td', {'class': 'colSecs'}).inject(row);
new Element( 'td', {'class': 'colFrames'} ).inject( row ); new Element('td', {'class': 'colFrames'}).inject(row);
new Element( 'td', {'class': 'colScore'} ).inject( row ); new Element('td', {'class': 'colScore'}).inject(row);
new Element( 'td', {'class': 'colDelete'} ).inject( row ); new Element('td', {'class': 'colDelete'}).inject(row);
var link = new Element( 'a', {'href': '#', 'events': {'click': createEventPopup.pass( [event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height] )}}); var link = new Element('a', {
link.set( 'text', event.Id ); 'href': '#',
link.inject( row.getElement( 'td.colId' ) ); 'events': {
'click': createEventPopup.pass( [
zm_event.Id,
'&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1',
zm_event.Width,
zm_event.Height
] )
}
});
link.set('text', zm_event.Id);
link.inject(row.getElement('td.colId'));
link = new Element( 'a', {'href': '#', 'events': {'click': createEventPopup.pass( [event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height] )}}); link = new Element('a', {
link.set( 'text', event.Name ); 'href': '#',
link.inject( row.getElement( 'td.colName' ) ); 'events': {
'click': createEventPopup.pass( [
zm_event.Id,
'&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1',
zm_event.Width,
zm_event.Height
] )
}
});
link.set('text', zm_event.Name);
link.inject(row.getElement('td.colName'));
row.getElement( 'td.colTime' ).set( 'text', event.StartTime ); row.getElement('td.colTime').set('text', zm_event.StartTime);
row.getElement( 'td.colSecs' ).set( 'text', event.Length ); row.getElement('td.colSecs').set('text', zm_event.Length);
link = new Element( 'a', {'href': '#', 'events': {'click': createFramesPopup.pass( [event.Id, event.Width, event.Height] )}}); link = new Element('a', {'href': '#', 'events': {'click': createFramesPopup.pass( [zm_event.Id, zm_event.Width, zm_event.Height] )}});
link.set( 'text', event.Frames+'/'+event.AlarmFrames ); link.set('text', zm_event.Frames+'/'+zm_event.AlarmFrames);
link.inject( row.getElement( 'td.colFrames' ) ); link.inject(row.getElement('td.colFrames'));
link = new Element( 'a', {'href': '#', 'events': {'click': createFramePopup.pass( [event.Id, '0', event.Width, event.Height] )}}); link = new Element('a', {'href': '#', 'events': {'click': createFramePopup.pass( [zm_event.Id, '0', zm_event.Width, zm_event.Height] )}});
link.set( 'text', event.AvgScore+'/'+event.MaxScore ); link.set('text', zm_event.AvgScore+'/'+zm_event.MaxScore);
link.inject( row.getElement( 'td.colScore' ) ); link.inject(row.getElement('td.colScore'));
link = new Element( 'button', { link = new Element('button', {
'type': 'button', 'type': 'button',
'title': deleteString, 'title': deleteString,
'data-event-id': event.Id, 'data-event-id': zm_event.Id,
'events': { 'events': {
'click': function(e) { 'click': function(e) {
var event_id = e.target.getAttribute('data-event-id'); var event_id = e.target.getAttribute('data-event-id');
@ -608,14 +628,14 @@ function getEventCmdResponse( respObj, respText ) {
} }
} }
} else { } else {
row.getElement('td.colName a').set('text', event.Name); row.getElement('td.colName a').set('text', zm_event.Name);
row.getElement('td.colSecs').set('text', event.Length); row.getElement('td.colSecs').set('text', zm_event.Length);
row.getElement('td.colFrames a').set('text', event.Frames+'/'+event.AlarmFrames); row.getElement('td.colFrames a').set('text', zm_event.Frames+'/'+zm_event.AlarmFrames);
row.getElement('td.colScore a').set('text', event.AvgScore+'/'+event.MaxScore); row.getElement('td.colScore a').set('text', zm_event.AvgScore+'/'+zm_event.MaxScore);
row.removeClass('recent'); row.removeClass('recent');
} }
row.addClass('updated'); row.addClass('updated');
} } // end foreach event
var rows = $(eventListBody).getElements('tr'); var rows = $(eventListBody).getElements('tr');
for ( var i = 0; i < rows.length; i++ ) { for ( var i = 0; i < rows.length; i++ ) {
@ -631,7 +651,7 @@ function getEventCmdResponse( respObj, respText ) {
} }
} else { } else {
checkStreamForErrors('getEventCmdResponse', respObj); checkStreamForErrors('getEventCmdResponse', respObj);
} } // end if objresult == ok
var eventCmdTimeout = eventsRefreshTimeout; var eventCmdTimeout = eventsRefreshTimeout;
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) { if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
@ -672,7 +692,8 @@ function getControlResponse(respObj, respText) {
} }
} }
function controlCmd(button) { function controlCmd(event) {
button = event.target;
control = button.getAttribute('value'); control = button.getAttribute('value');
xtell = button.getAttribute('xtell'); xtell = button.getAttribute('xtell');
ytell = button.getAttribute('ytell'); ytell = button.getAttribute('ytell');
@ -687,7 +708,7 @@ function controlCmd(button) {
var y = event.pageY - coords.top; var y = event.pageY - coords.top;
if ( xtell ) { if ( xtell ) {
var xge = parseInt( (x*100)/coords.width ); var xge = parseInt((x*100)/coords.width);
if ( xtell == -1 ) { if ( xtell == -1 ) {
xge = 100 - xge; xge = 100 - xge;
} else if ( xtell == 2 ) { } else if ( xtell == 2 ) {
@ -696,7 +717,7 @@ function controlCmd(button) {
locParms += '&xge='+xge; locParms += '&xge='+xge;
} }
if ( ytell ) { if ( ytell ) {
var yge = parseInt( (y*100)/coords.height ); var yge = parseInt((y*100)/coords.height);
if ( ytell == -1 ) { if ( ytell == -1 ) {
yge = 100 - yge; yge = 100 - yge;
} else if ( ytell == 2 ) { } else if ( ytell == 2 ) {

View File

@ -782,20 +782,23 @@ include('_monitor_source_nvsocket.php');
} else if ( $monitor->Type() == 'Remote' ) { } 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> <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
?>
<tr>
<td><?php echo translate('RemoteMethod') ?></td>
<td>
<?php <?php
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) { if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
?> echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method() );
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $httpMethods, $monitor->Method() ); ?></td></tr>
<?php
} else { } else {
?> echo htmlSelect('newMonitor[Method]', $rtspMethods, $monitor->Method() );
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspMethods, $monitor->Method() ); ?></td></tr>
<?php
} }
?> ?>
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr> </td>
</tr>
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>"/></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('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> <tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
<?php <?php
} else if ( $monitor->Type() == 'File' ) { } else if ( $monitor->Type() == 'File' ) {
?> ?>
@ -803,23 +806,44 @@ include('_monitor_source_nvsocket.php');
<?php <?php
} elseif ( $monitor->Type() == 'cURL' ) { } elseif ( $monitor->Type() == 'cURL' ) {
?> ?>
<tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr> <tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>" size="12"/></td></tr> <tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/></td></tr>
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>" size="12"/></td></tr> <tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/></td></tr>
<?php <?php
} elseif ( $monitor->Type() == 'WebSite' ) { } elseif ( $monitor->Type() == 'WebSite' ) {
?> ?>
<tr><td><?php echo translate('WebSiteUrl') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr> <tr>
<tr><td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4";"/></td></tr> <td><?php echo translate('WebSiteUrl') ?></td>
<tr><td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4";"/></td></tr> <td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td>
<tr><td><?php echo 'Web Site Refresh (Optional)' ?></td><td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()); ?>"/></td></tr> </tr>
<tr>
<td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td>
<td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td>
<td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo 'Web Site Refresh (Optional)' ?></td>
<td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()) ?>"/></td>
</tr>
<?php <?php
} elseif ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) { } else if ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
?> ?>
<tr class="SourcePath"><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" /></td></tr> <tr class="SourcePath">
<tr><td><?php echo translate('RemoteMethod') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspFFMpegMethods, $monitor->Method() ); ?></td></tr> <td><?php echo translate('SourcePath') ?></td>
<td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" /></td>
</tr>
<tr>
<td><?php
echo translate('RemoteMethod');
echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' );
?>)</td>
<td><?php echo htmlSelect('newMonitor[Method]', $rtspFFMpegMethods, $monitor->Method()) ?></td>
</tr>
<tr class="SourceOptions"> <tr class="SourceOptions">
<td><?php echo translate('Options') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td> <td><?php echo translate('Options') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
<td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/></td> <td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/></td>
</tr> </tr>
<?php <?php
@ -840,10 +864,12 @@ include('_monitor_source_nvsocket.php');
</tr> </tr>
<?php <?php
} }
if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
?> ?>
<tr><td><?php echo translate('TargetColorspace') ?></td><td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours() ); ?> <tr>
</td></tr> <td><?php echo translate('TargetColorspace') ?></td>
<td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours()) ?></td>
</tr>
<tr> <tr>
<td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td> <td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td>
<td> <td>
@ -884,18 +910,22 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
<td><?php echo htmlselect('newMonitor[Orientation]', $orientations, $monitor->Orientation());?></td> <td><?php echo htmlselect('newMonitor[Orientation]', $orientations, $monitor->Orientation());?></td>
</tr> </tr>
<?php <?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 validHtmlStr($value); ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr> <tr>
<?php <td><?php echo translate('Deinterlacing') ?></td>
<td><?php echo htmlselect('newMonitor[Deinterlacing]', $deinterlaceopts_v4l2, $monitor->Deinterlacing())?></td>
</tr>
<?php
} else if ( $monitor->Type() != 'WebSite' ) { } else if ( $monitor->Type() != 'WebSite' ) {
?> ?>
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr> <tr>
<td><?php echo translate('Deinterlacing') ?></td>
<td><?php echo htmlselect('newMonitor[Deinterlacing]', $deinterlaceopts, $monitor->Deinterlacing())?></td>
</tr>
<?php <?php
} }
?>
<?php
if ( $monitor->Type() == 'Remote' ) { if ( $monitor->Type() == 'Remote' ) {
?> ?>
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( $monitor->RTSPDescribe() ) { ?> checked="checked"<?php } ?>/></td></tr> <tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( $monitor->RTSPDescribe() ) { ?> checked="checked"<?php } ?>/></td></tr>
@ -939,15 +969,17 @@ if ( $monitor->Type() == 'Local' ) {
$videowriteropts[1] = 'X264 Encode'; $videowriteropts[1] = 'X264 Encode';
if ($monitor->Type() == 'Ffmpeg' ) if ( $monitor->Type() == 'Ffmpeg' )
$videowriteropts[2] = 'H264 Camera Passthrough'; $videowriteropts[2] = 'H264 Camera Passthrough';
else else
$videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1); $videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1);
echo htmlselect( 'newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter() ); echo htmlselect('newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter());
?> ?>
</td></tr> </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('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> <tr><td><?php echo translate('RecordAudio') ?></td><td>
<?php if ( $monitor->Type() == 'Ffmpeg' ) { ?> <?php if ( $monitor->Type() == 'Ffmpeg' ) { ?>
<input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/> <input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/>
@ -962,22 +994,52 @@ if ( $monitor->Type() == 'Local' ) {
case 'timestamp' : case 'timestamp' :
{ {
?> ?>
<tr><td><?php echo translate('TimestampLabelFormat') ?></td><td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat()) ?>" size="32"/></td></tr> <tr>
<tr><td><?php echo translate('TimestampLabelX') ?></td><td><input type="text" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td></tr> <td><?php echo translate('TimestampLabelFormat') ?></td>
<tr><td><?php echo translate('TimestampLabelY') ?></td><td><input type="text" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td></tr> <td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat()) ?>"/></td>
<tr><td><?php echo translate('TimestampLabelSize') ?></td><td><select name="newMonitor[LabelSize]"><?php foreach ( $label_size as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->LabelSize() ) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr> </tr>
<tr>
<td><?php echo translate('TimestampLabelX') ?></td>
<td><input type="number" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('TimestampLabelY') ?></td>
<td><input type="number" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('TimestampLabelSize') ?></td>
<td><?php echo htmlselect('newMonitor[LabelSize]', $label_size, $monitor->LabelSize()) ?></td>
</tr>
<?php <?php
break; break;
} }
case 'buffers' : case 'buffers' :
{ {
?> ?>
<tr><td><?php echo translate('ImageBufferSize') ?></td><td><input type="text" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td></tr> <tr>
<tr><td><?php echo translate('WarmupFrames') ?></td><td><input type="text" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td></tr> <td><?php echo translate('ImageBufferSize') ?></td>
<tr><td><?php echo translate('PreEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td></tr> <td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td>
<tr><td><?php echo translate('PostEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" size="4"/></td></tr> </tr>
<tr><td><?php echo translate('StreamReplayBuffer') ?></td><td><input type="text" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" size="6"/></td></tr> <tr>
<tr><td><?php echo translate('AlarmFrameCount') ?></td><td><input type="text" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td></tr> <td><?php echo translate('WarmupFrames') ?></td>
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('PreEventImageBuffer') ?></td>
<td><input type="number" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('PostEventImageBuffer') ?></td>
<td><input type="number" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" size="4"/></td>
</tr>
<tr>
<td><?php echo translate('StreamReplayBuffer') ?></td>
<td><input type="number" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" size="6"/></td>
</tr>
<tr>
<td><?php echo translate('AlarmFrameCount') ?></td>
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td>
</tr>
<?php <?php
break; break;
} }
@ -986,7 +1048,8 @@ if ( $monitor->Type() == 'Local' ) {
?> ?>
<tr> <tr>
<td><?php echo translate('Controllable') ?></td> <td><?php echo translate('Controllable') ?></td>
<td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( $monitor->Controllable() ) { ?> checked="checked"<?php } ?>/></td></tr> <td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( $monitor->Controllable() ) { ?> checked="checked"<?php } ?>/></td>
</tr>
<tr> <tr>
<td><?php echo translate('ControlType') ?></td> <td><?php echo translate('ControlType') ?></td>
<td><?php echo htmlSelect('newMonitor[ControlId]', $controlTypes, $monitor->ControlId()); <td><?php echo htmlSelect('newMonitor[ControlId]', $controlTypes, $monitor->ControlId());
@ -1011,20 +1074,19 @@ if ( canEdit('Control') ) {
<td><?php echo translate('TrackMotion') ?></td> <td><?php echo translate('TrackMotion') ?></td>
<td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td> <td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td>
</tr> </tr>
<?php
$return_options = array(
'-1' => translate('None'),
'0' => translate('Home'),
'1' => translate('Preset').' 1',
);
?>
<tr> <tr>
<td><?php echo translate('TrackDelay') ?></td> <td><?php echo translate('TrackDelay') ?></td>
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td> <td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td>
</tr> </tr>
<tr> <tr>
<td><?php echo translate('ReturnLocation') ?></td> <td><?php echo translate('ReturnLocation') ?></td>
<td><?php echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnLocation()); ?></td> <td><?php
$return_options = array(
'-1' => translate('None'),
'0' => translate('Home'),
'1' => translate('Preset').' 1',
);
echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnLocation()); ?></td>
</tr> </tr>
<tr> <tr>
<td><?php echo translate('ReturnDelay') ?></td> <td><?php echo translate('ReturnDelay') ?></td>

View File

@ -1,6 +1,6 @@
<?php <?php
// //
// ZoneMinder web watch feed view file, $Date$, $Revision$ // ZoneMinder web watch feed view file
// Copyright (C) 2001-2008 Philip Coombes // Copyright (C) 2001-2008 Philip Coombes
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -46,17 +46,16 @@ if ( isset($_REQUEST['scale']) ) {
} else if ( isset($_COOKIE['zmWatchScale'.$mid]) ) { } else if ( isset($_COOKIE['zmWatchScale'.$mid]) ) {
$scale = $_COOKIE['zmWatchScale'.$mid]; $scale = $_COOKIE['zmWatchScale'.$mid];
} else { } else {
$scale = reScale(SCALE_BASE, $monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE); $scale = $monitor->DefaultScale();
} }
$connkey = generateConnKey(); $connkey = generateConnKey();
$streamMode = getStreamMode(); $streamMode = getStreamMode();
noCacheHeaders();
$popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1)); $popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1));
noCacheHeaders();
xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed')); xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed'));
?> ?>
<body> <body>
@ -77,7 +76,7 @@ if ( canView('Control') && $monitor->Type() == 'Local' ) {
<div id="closeControl"><a href="#" data-on-click="<?php echo $popup ? 'closeWindow' : 'backWindow' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div> <div id="closeControl"><a href="#" data-on-click="<?php echo $popup ? 'closeWindow' : 'backWindow' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div>
</div> </div>
<?php <?php
if ( $monitor->Status() != 'Connected' ) { if ( $monitor->Status() != 'Connected' and $monitor->Type() != 'WebSite' ) {
echo '<div class="warning">Monitor is not capturing. We will be unable to provide an image</div>'; echo '<div class="warning">Monitor is not capturing. We will be unable to provide an image</div>';
} }
?> ?>