From 84ed491765a89ff7de47e993f33a9d5a2dff455c Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Wed, 22 Jul 2015 13:51:31 -0400 Subject: [PATCH 001/105] Initial Montage Review for people to take a look at --- web/skins/classic/views/console.php | 6 +- web/skins/classic/views/montagereview.php | 688 ++++++++++++++++++++++ 2 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 web/skins/classic/views/montagereview.php diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 5930ebe95..f7724d6e7 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -210,7 +210,11 @@ if ( canView( 'Stream' ) && $cycleCount > 1 ) { $cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0; ?> -
 / 
+
+  /  +  /  + +
0 "; + +// This program only calls itself with the time range involved -- it does all monitors (the user can see) all the time + +if ( !empty($user['MonitorIds']) ) +{ + $monFilterSql = ' AND M.Id IN ('.$user['MonitorIds'].')'; + + $eventsSql .= $monFilterSql; + $monitorsSQL .= $monFilterSql; + $frameSql .= $monFilterSql; +} + +// Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. + +if ( isset($_REQUEST['minTime']) ) + $minTime = validHtmlStr($_REQUEST['minTime']); + +if ( isset($_REQUEST['maxTime']) ) + $maxTime = validHtmlStr($_REQUEST['maxTime']); + +if ( isset($_REQUEST['scale']) ) + $defaultScale=validHtmlStr($_REQUEST['scale']); +else + $defaultScale=0.3; + +if (isset($_REQUEST['speed']) ) + $defaultSpeed=validHtmlStr($_REQUEST['speed']); +else + $defaultSpeed=1; + +if (isset($_REQUEST['current']) ) + $defaultCurrentTime=validHtmlStr($_REQUEST['current']); + +$archive=1; +if (isset($_REQUEST['archive']) ) + $archive=validHtmlStr($_REQUEST['archive']); + +if ($archive==0) +{ + $eventsSql .= " and E.Archived=0 "; +} $frameSql .= " and E.Archived=0 "; + +$eventsSql .= "group by E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId "; + +if( isset($minTime) && isset($maxTime) ) +{ + $eventsSql .= "having CalcEndTime > '" . $minTime . "' and StartTime < '" . $maxTime . "'"; + $frameSql .= " + and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; +} +$frameSql .= "group by E.Id, E.MonitorId, F.TimeStamp order by E.MonitorId, F.TimeStamp asc"; + +xhtmlHeaders(__FILE__, translate('montagereview') ); +?> + + + +
+ + +
+ + step=0.10 width=20% onchange='changescale(this.value)'/> + x +
+
+ + step=1 wdth=20% onchange='changespeed(this.value)'/> + x +
+
+ + + + + + + +
+ +
+ + + + +
+ + +\n"; +echo "var eventMonitorId = [];\n"; +echo "var eventId = [];\n"; +echo "var eventStartTimeSecs = [];\n"; +echo "var eventEndTimeSecs = [];\n"; +echo "var eventPath = [];\n"; +echo "var eventFrames = [];\n"; // this is going to presume all frames equal durationlength + +// Because we might not have time as the criteria, figure out the min/max time when we run the query + +$minTimeSecs = strtotime("2036-01-01 01:01:01"); +$maxTimeSecs = strtotime("1950-01-01 01:01:01"); + +$index=0; +$anyAlarms=false; +$eventsMonitorsFound = array(); // this will just flag which ones found + +foreach( dbFetchAll( $eventsSql ) as $event ) +{ + if( $minTimeSecs > strtotime($event['StartTime'])) $minTimeSecs=strtotime($event['StartTime']); + if( $maxTimeSecs < strtotime($event['CalcEndTime'])) $maxTimeSecs=strtotime($event['CalcEndTime']); + echo "eventMonitorId[$index]=" . $event['MonitorId'] . "; eventId[$index]=" . $event['Id'] . "; "; + echo "eventStartTimeSecs[$index]=" . strtotime($event['StartTime']) . "; eventEndTimeSecs[$index]=" . strtotime($event['CalcEndTime']) . "; "; + echo "eventFrames[$index]=" . $event['Frames'] . "; "; + + if ( ZM_USE_DEEP_STORAGE ) + echo "eventPath[$index] = \"events/" . $event['MonitorId'] . "/" . strftime("%y/%m/%d/%H/%M/%S", strtotime($event['StartTime'])) . "/\";" ; + else + echo "eventPath[$index] = \"events/" . $event['MonitorId'] . "/" . $event['Id'] . "/\";" ; + $eventsMonitorsFound[$event['MonitorId']] = true; + $index=$index+1; + if($event['MaxScore']>0) + $anyAlarms=true; + echo "\n"; +} + +if($index == 0) // if there is no data set the min/max to the passed in values +{ + if(isset($minTime) && isset($maxTime)) + { + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); + } + else // this is the case of no passed in times AND no data -- just set something arbitrary + { + $minTimeSecs=strtotime('1950-06-01 01:01:01'); // random time so there's something to display + $maxTimeSecs=strtotime('2020-06-02 02:02:02'); + } +} + +// We only reset the calling time if there was no calling time +if(!isset($minTime) || !isset($maxTime)) +{ + $maxTime = strftime($maxTimeSecs); + $minTime = strftime($minTimeSecs); +} +else +{ + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); +} + +// If we had any alarms in those events, this builds the list of all alarm frames (thought for later - should these be ranges, so as to minimize list if very long?) + +echo "var frameMonitorId = [];\n"; +echo "var frameTimeStampSecs = [];\n"; +echo "var frameScore = [];\n"; +$maxScore=0; +$index=0; + +if($anyAlarms) + foreach( dbFetchAll ($frameSql) as $frame ) + { + echo " frameMonitorId[$index]=" . $frame['MonitorId'] . ";"; + echo " frameTimeStampSecs[$index]=" . strtotime($frame['TimeStamp']) . ";"; + echo " frameScore[$index]=" . $frame['Score'] . ";\n"; + if($maxScore <= $frame['Score']) + $maxScore=$frame['Score']; + $index += 1; + } + +// This is where we have to display the canvases -- AFTER determining which monitors we use (above in events) and BEFORE we loop through them to cache the objects +// This splits up the javascript and html a bit, but it's a lot simpler than trying in php to cache one while completing the other + +// Monitor images - these had to be loaded after the monitors used were determined (after loading events) + +echo "\n"; + +foreach ($monitors as $m) +{ + if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events + { + echo "No Canvas Support!!\n"; + } +} +echo " + +
+ + + + From b88403cd416cbbd20dbee93efc3f763baa96841c Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:01:53 -0400 Subject: [PATCH 002/105] Minor corrections based on feedback to date --- src/zm_event.cpp | 56 ++++++++++----- src/zm_event.h | 6 ++ src/zm_image.cpp | 42 ++++++++++- src/zm_image.h | 7 +- web/api/app/Config/core.php | 4 +- web/graphics/NoDataImage.gif | Bin 0 -> 7002 bytes web/skins/classic/views/montagereview.php | 81 +++++++++++++++------- 7 files changed, 149 insertions(+), 47 deletions(-) create mode 100644 web/graphics/NoDataImage.gif diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 3e723fa48..b173d9e0c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -67,6 +67,14 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string if ( !initialised ) Initialise(); +// >>> Real time image extrat settings <<< these need to go in conf options + + UpldCount=0; + strcpy(UpldPath,"/home/ferguson/ToUpload"); + UpldWriteEvery=600; + UpldWriteEveryAlarm=2; + + std::string notes; createNotes( notes ); @@ -349,28 +357,42 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame ) bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) { - if ( config.timestamp_on_capture ) + bool toUpld=false; + char UpldFile[PATH_MAX]; + char UpldFileRename[PATH_MAX]; + if( ( UpldCount++ % (alarm_frame ? UpldWriteEveryAlarm : UpldWriteEvery) ) == 0) // notice this grabs frame #1 so it gets the first of every event (zero count = frame 1) { - if ( !config.opt_frame_server || !SendFrameImage( image, alarm_frame) ) - { - if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) - image->WriteJpeg( event_file, config.jpeg_alarm_file_quality ); - else - image->WriteJpeg( event_file ); - } + toUpld=true; + char tmbuf[64], buf[64]; + strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d-%H-%M-%S", localtime(&(timestamp.tv_sec))); + snprintf(buf, sizeof buf, "%s-%06d", tmbuf,(int)(timestamp.tv_usec)); + snprintf(UpldFile, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg_saving",UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); + snprintf(UpldFileRename, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg", UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); + } + + Image* ImgToWrite; + Image ts_image( *image ); + + if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. + { + monitor->TimestampImage( &ts_image, ×tamp ); + ImgToWrite=&ts_image; } else + ImgToWrite=image; + + if ( !config.opt_frame_server || !SendFrameImage( ImgToWrite, alarm_frame) ) { - Image ts_image( *image ); - monitor->TimestampImage( &ts_image, ×tamp ); - if ( !config.opt_frame_server || !SendFrameImage( &ts_image, alarm_frame) ) - { - if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) - ts_image.WriteJpeg( event_file, config.jpeg_alarm_file_quality ); - else - ts_image.WriteJpeg( event_file ); + int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use + ImgToWrite->WriteJpeg( event_file, thisquality, timestamp ); + if(toUpld) + { // Because these are for real-time use and may be grabbed as they are being written, write under one name then rename + ImgToWrite->WriteJpeg(UpldFile, thisquality, timestamp); + if(rename(UpldFile, UpldFileRename)!=0) + Error ("Failure to rename real time capture file %s to %s, ignored",UpldFile, UpldFileRename); } } + return( true ); } @@ -885,7 +907,7 @@ void EventStream::processCommand( const CmdMsg *msg ) } // If we are in single event mode and at the last frame, replay the current event - if ( (mode == MODE_SINGLE) && (curr_frame_id == event_data->frame_count) ) + if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) curr_frame_id = 1; replay_rate = ZM_RATE_BASE; diff --git a/src/zm_event.h b/src/zm_event.h index f50a5bf06..412baa0bb 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -59,6 +59,12 @@ protected: protected: static int sd; +private: + int UpldCount; + char UpldPath[PATH_MAX]; + int UpldWriteEvery; + int UpldWriteEveryAlarm; + public: typedef std::set StringSet; typedef std::map StringSetMap; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 8f91ab28b..c1e91a00d 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -787,7 +787,22 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int return( true ); } -bool Image::WriteJpeg( const char *filename, int quality_override ) const +// Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults. + +bool Image::WriteJpeg( const char *filename, int quality_override) const +{ + return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); +} +bool Image::WriteJpeg( const char *filename) const +{ + return Image::WriteJpeg(filename, 0, (timeval){0,0}); +} +bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const +{ + return Image::WriteJpeg(filename,0,timestamp); +} + +bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const { if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { @@ -795,7 +810,6 @@ bool Image::WriteJpeg( const char *filename, int quality_override ) const temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); return( temp_image.WriteJpeg( filename, quality_override ) ); } - int quality = quality_override?quality_override:config.jpeg_file_quality; struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; @@ -887,6 +901,30 @@ bool Image::WriteJpeg( const char *filename, int quality_override ) const jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); } + if(timestamp.tv_sec) + { + #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds + #define EXIFTIMES_MS_LEN 0x03 + #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes + #define EXIFTIMES_LEN 0x13 // = 19 + #define EXIF_CODE 0xE1 + + char timebuf[64], msbuf[64]; + strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); + snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it + unsigned char exiftimes[82] = { + 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00 }; + memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); + memcpy(&exiftimes[EXIFTIMES_MS_OFFSET],msbuf ,EXIFTIMES_MS_LEN); // first character after the decimal point + jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); + + } + JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) diff --git a/src/zm_image.h b/src/zm_image.h index 46c7a031b..a48fafacc 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -204,7 +204,12 @@ public: bool WriteRaw( const char *filename ) const; bool ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder); - bool WriteJpeg( const char *filename, int quality_override=0 ) const; + + bool WriteJpeg ( const char *filename) const; + bool WriteJpeg ( const char *filename, int quality_override ) const; + bool WriteJpeg ( const char *filename, struct timeval timestamp ) const; + bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const; + bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder); bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const; diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 436cf8d60..59d72162c 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,12 +222,12 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', 'Q0MjGG2xRQEhJVQR85WhFJKI7f2St8RYMlVR7GNQ'); + Configure::write('Security.salt', 'olX2TOlboOnC474y3Tk4W4JOyuirw1EaadeHCcr4'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ - Configure::write('Security.cipherSeed', '02670120062639232092038865362'); + Configure::write('Security.cipherSeed', '84684583012508019120061282965'); /** * Apply timestamps with the last modified time to static assets (js, css, images). diff --git a/web/graphics/NoDataImage.gif b/web/graphics/NoDataImage.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff97eb1a96f13e5caaba7a7707bea402a1be4e5a GIT binary patch literal 7002 zcmV-g8>Qq&Nk%w1VITuo0`wdJ9v&VwH8n>^M_E}}X=!PCdU}b8iIlq)=jZ9^>F)0C^78WY^Yi!j_xk$! z|Ns900000000000A^8LV00000EC2ui03ZWc0ssa6ASaGwX`X1Ru59bRa4gSsZQppV z?|kq7z@TtQEE41ejE#0PICJXU$+M@= zpFo2O9ZIyQ(W6L{DqYI7sne%Wqe`7hwW`&tShH%~%C)Q4uVBN99ZR;X*|TWVs$I*r zt=qS7(BTJr4xw7TUm@{kM z%(=7Y&!9t#9!C>oFt6t5zwd>cgW6PdRySDAyxO3~?&AYen-@tIW33Tb7JWU8QKk6TV5=9lt>Ddvd? zlp-Ml1;}aQnK=f4WD0BM*rpV3MmZ;ob*56|PX~0Ur-=oqut1(27HMLK2vmRtg&o!? zfTM}ZlR%@7hB$zu6~cIcDvJt*rVEdPQDdn2)YxVQ37iP$DXo&&=btOY`o*mL*ouOM zCGKiUuR!@2DGS1SLF_)p{+@8arL4j@l#pqv5N#LJ>Qk)=3z#TCwmQ1%qo2W^C@YM# z;xldu8MvE@r7LbLR{($t5F@z@0fe`e_Rh5-{_JpJqyf&pL!`H29tYQ1Z)NviIT z*djp&LfN4Sx{+REJe46Imjl?%3#B?7s@_nAY;}G;loS-%wp!KjH*l~jIzlAWU?rD96;FkQ1HwW4d8J6ThR(d z@W*%h(M0R?-VX1HOBz-aSl1k93AzaYVEG7~g!Cqe&`E-f2|z+JtI;xZ(##B4F`pcW z=l%=}2qSP-07kF8!S_POAyLjUjPoQx6HOF=iVd!CDA1^hJjsDHvb1}pG!Z(@7g7?($}vr$7#)F4XIg?pvS_F`X(ln}Wxy$Zltnb-RzEO%4u_iceiOPz~OlIr^&z&qE{}qB^dII2<$hya6k^fMMf_+wQyJn25aJ7|O`kDZ~Bnahh zSL8Qf8h}akQWa|YQ2RExsoK@83Cs)G{7U$~o#pOlH<%;PiI-f= zA_0X%#85lBmxvA~!HGG$qM`b4#0iV+U;~+95-4`YEG{i<7i<8v{-CHO*l~qLTqA}? zSH^piE`({k zMDi`P1!Mb3D~9aQ1k-hnwW`lcqZQCvHnxhhOhW{Gcgf((D+%8GA)vaDf=U!qA158= zNGEy(V|DdeV-0OsV_H|WMs^m*z3fc;YRV)K@{=6hZg-!X*qU7NKrKz_WZRpF;>59& zOGMLK8}{C$!=O}!NN1wzo7eS5ce?St?sCg|*pT+Ox`WE@Sx-;HAF89lnT=*)mz+gq z<#NB3x^aw$NX#T(>$T53^59u@44V(=K}7(7D!$N;l}!k%!YKN6aC|bKltlI)b^q8+Ua^OBybh3AU<3|GQH+K{`fr)2*DR6eW2SfmLR6eJG#}(LIa3=!>0|QqgnN(GAgJg9Cd@yi&D$si+AL4qo9gM`;x3wARw761tre}IT$^v7=$7j0mbJQFlg z3ott=2Lp0QGi?$f5k*!dP*`!bhX9~(S|@)n{sbeWc!-H8h!4d$&$a^RM{)^70CIyX zV}w;Q5jBr;XSEYk%9H|Ql}A*Ef;50CHF9UP!YQ}-g(8puVsll@NInz-QXLXO@)kW1 z^<4qLI3-h6yO;wvCsBAtRl&E7C^L*F0);HFG!t@+sB!?A#{$8qN}<$z7FA5BGDs4l zTv}r>&B!>Ycqc@rOpEp*NE3}YK~TFRc6ujA614zn^Mp4LYBhFC*k)!QsE{#sj|#Ob ze>7S*ppkYqf4k%;sF;W?Ab0l1LJt{{kyvR8)gmI9D026A_9K8Xp^;rMsm?J>B0tMM6ljlU> zmm?*>liq}rFrkwxbA(&@l0n%ea6*w+W|UUuBU0IsRk$u+h>{{Om4Z^0U2=(7IVYtz zZHJBQ#khRTXezsS|4HWwuvUikUg0CzJ~IfpiIpc6paMVmRHjD_`j& z20&nSC?o-30D0FX0uYrcnUydQ0hwu#SLsilLMCn5nA1{|dSoOvQ$lF@5|z0Ew}zNf z^_34bgHXena`|zesgV_=K4KJ)BNqVq)RwFXgU(ZZ18@LWDQAKS11d>;GT=Tv(ws8j ze`2&kQ~63WIhMTFe+EZMm81Sc@uL+$^Mwh(mnTpGE#o)@P%*NZ2)I%JMRF<#z)-`8 zGzNeG3s7Qy$uY7SG895M1uCHphc+#vCz!GT0NMotT0Bo;pc6Sd0)RIspivZKG0sT@ z0-819$xw47OBOSt4Wc}pv{@AzxXXN$L>` zU_3s$L1QJQQ>qc}S#%w^S6gZl%LgKm*Mng?61c?z;fQ!=3KDGSOj6jU95Ge_0DVg; zK5|MD-Gn!)qamzAj(Mu2w|OOjS`uR_CIXO~g~}0kN;>Shs3##iQnI3o3aKIy0cs;P zrqUts7>1Vmsh}FFqW(Inq*|(`da9_Js;auGtlFxs`l_%RtFk()v|6jSdaJmatGc?Y zyxOb2`m4Yitin31#9FMzdaTHrtjfBq%-XEZ`mE3ztdawAJull;L{MxVn`mX>R zumU@<1Y58Md$0(bunN1d4BM~{`>+rju@XD66kD+td$Aasu^PLv9NV!T`>`M!vLZXO zO|StMU;z^#0S?dr3P7?nkO2^~017a(3g7?_FaZ~^2p3QRDZ8>X`?E8<3KuW|IJ*I+ zS^*3Iv`VW0{s+nj7qGNYn+g_?v_IRlVVVIf3$;Ky0g3RmS_`zOFac0om|I!_GW)eZ zo3n`EwP+i(rogsKtD{LOwrxwZmFfp@i?*lm0AJexmRbRI`?FlzwSn8RrqH&K3b=)< z01IHWiJ$=!&}MpjxRV>G8gRBs+W?Mh0TOVwgS!Wis{t@jxn>Z$NMO1z-~eAswj&Y& zT5AEH^tpJD0TYn5YU=`|D+aV{yG5|OGkd!&AOT-1w-~YkUmK%v0J&L9v%t#&t2+kD z3$)GK1JRqdF|fQq>$iofxKWF@e7m&Ms{+pp1{d(XN*lg8P`*%$zA3N)*gLZh;JAV6 zx?21G2VX0{Eik@caKAvnzcNq(s=ELWK)flUy7k)!8t}C-pub&^zz6ID4&1%A`o3V> z2YFk;FTlWDaKS$d1RPAWxSG3p@WF1I!CK3@Q9#0m>jNqr!V266bSuHQd%|E4!%GVU zHmtNR{J_yS0S{onGYgRsPyzT00~s*1DvNg}P`*ja01f~FL_7mIjKMQJwk5CuKFqQL zOu#8Hv_G7+co(Bn+`&IE#vp717cjJu%d#zSvJ()q(`x|`K(!4p0Yyv#SPaAtV8>`2 zxm2qFPCNmk8yo;k!G(*y8V~`P`?V1;$Q{VD5a0lR{Igpkyh|&)Dv-!*w#bXC0Mq`f zzZU=jP`d!^y8;)W$g2xN8W71E(#h8Q0;{~quFSk7kj6yIW<0!BLmRV~Y-5vbx3F6R ziOk7C%*7ml#lNhyp6VNxJj=gp0$A+I5^%?Z)V560%t{-~ETF=NYy!`F0YI#^n9Kqd zV8~FLh};~wrM$$>EWIO;&SyLV*sQgna{s$gE{k6B7(Iqg@lx)#;t0`t1xH`H4 z=3BT{`x+u$x4=s@?W_O@Z36eK!^eEnjQau|t+fz6(?6@tDKO8AJH0)ytqQm0ZNV2kPXze9JpKZ(vyw0Qe6To{j&|=$n+bx!J)w>AkwAn*h#?B4D^g^_e z8@LV7%9EXl+^e)VbJMg99Ij0QvJJE)Hqj`_$Y?78H89;PT*afz{>LIf)e+skzw7|u zwAxFny~{1bJmB6lFy12Y(hLyAh>f-)I>;Ar*-U!^8*tOgJpu!bysshPTQs~UAkxAu z+1Rb!joaS54d1g}+T|p|szkF4fWE+OJ0bqxEiU3fdodzC&KB^s>|K`Q-Q7T&*_tiR z;!VS(^tB}3<1an}g$pbu%j26<3zp>>OuF-M+&_0moFiy#fe&sRH!YSbBE-vX>zUNW?&g32q=rR7<9&OvUt>aY8 z8y4=~7lXEy-L_MH>3yE*R_y7et^&0C!wf#_A_nI+VCj!evog-d`3?&}k#*C-4diJtC0 zPVF??>aKpnql@euFy{k)>-5g+Sf1@EfasFm>Elk_C7{lKJUQ}@eeNoYu)CpE$6=uI&E%?!PD>-VDF;9*^^pzVXFww}M>P z7Qfp{KLa-3x>^$=rzvNYK_~Z`mcYnSHKhC18 zweHRw7M=kouk}znX__lB5!LRbmFZ{o6_Z!dmkUz8IJm^1L=2O?mBR~Ac zAJIij!V3WUq0jxSFV2pu0XrK3U5)tc5B~dF8{y@2*7W1Y zU;7}Sh$B~;<(QJEsj3rOKCaqa@ij$^Sj9guC>#=t#v?MRTr!)^Cp0RZQk}Vpgf?PK zx>(<-p%p<+8?hFK^NtmZhj*fxI@)dZHPYrzz}LOk9EXJ+9|TX^f{uekOr2d?(<7vd zT1kZjR-)GpM}&g|q86xH#ls{GX~_iystW^XnMnqv0%$0WY}GDrukSB#u<$Uk@I!Zv01iS~KA()xD0Ds!m2Ib+ufZpusvxbc!L~aftYFvWxTuBc2 z?r^xkQ6;#J$YSUTDPp3+oH}>%?CBFBNIUIJ1cjvQN6|4Bp-9^%Gv-EQ79rS7^`ogZ zCs=2iSUCoUOJw(;CROo+s?DW8*RpNv_U+HIR)1s=RcnETA#z=0pmGM~(}q!NEv;z> zf`+m~OZ?rIQb}WLDZNGt3zc$;a9Mwx+!moP+|Z&&lP(=)Z!#g#C~?6l1a*pC8!(T6 zBWN(CMz|r}HX*?r4KBA0(^#N8#_U?Qp(LlY`~>Y6Enh~r6G0ym zlP@17aVy{=9KZoR`oaVL^|shcsNi1V22=o!5g&lhMA&4Q0I3kH9ns_3LDXO?4i!HkNB8)N0I3tZU+IS<5 zIqJA0k3IVMBalG~IV6!q8hIp=Nh-M{lTAALB$QD~IVF`x&3q3T^MH_uI(n%}5G}BEx{WR23OFcE!Ra<>E)>&)4 zHP>Bx{WaKOi#;~kWt)9A+G(r3Hrs8x{Wjcj%RM*Ub=!S6-g)c2H{X5x{Wsu&3qCmE zg&Tf2;_-7|=~I_jybzB=oz zyZ$=tvCBR??X}x}JMOvbzB})|`~Exd!3#e;@x>c|Jo3pazdZBJJO4cN(Mvx)_0?N{ zJ@(mazdiTed;dN7;fp^$`Q@8`KKkjazdrlzyZ=7?@ykCy{q@^_KmPgazd!%|`~N=x z11P`&60m>uz?PIAOs^Q!3k2Zf)>0W1~aI^4RWx99{eB(Lny)#lCXp( sJRu5GsKOPpu!SysAq-
- + step=0.10 width=20% onchange='changescale(this.value)'/> x
- + step=1 wdth=20% onchange='changespeed(this.value)'/> x
- - - - - - - + + + + + + +
@@ -166,6 +186,7 @@ foreach( dbFetchAll( $monitorsSql ) as $row ) // This builds the list of events that are eligible from this range echo " From 3544fbd0a8ed6b7c14ed2e214aa15262674fcaf0 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:15:57 -0400 Subject: [PATCH 003/105] Remove unexpected files that were added --- src/zm_event.cpp | 62 ++++++++++++++++-------------------------------- src/zm_event.h | 6 ----- src/zm_image.cpp | 42 ++------------------------------ src/zm_image.h | 7 +----- 4 files changed, 23 insertions(+), 94 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index b173d9e0c..3e723fa48 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -67,14 +67,6 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string if ( !initialised ) Initialise(); -// >>> Real time image extrat settings <<< these need to go in conf options - - UpldCount=0; - strcpy(UpldPath,"/home/ferguson/ToUpload"); - UpldWriteEvery=600; - UpldWriteEveryAlarm=2; - - std::string notes; createNotes( notes ); @@ -357,42 +349,28 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame ) bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) { - bool toUpld=false; - char UpldFile[PATH_MAX]; - char UpldFileRename[PATH_MAX]; - if( ( UpldCount++ % (alarm_frame ? UpldWriteEveryAlarm : UpldWriteEvery) ) == 0) // notice this grabs frame #1 so it gets the first of every event (zero count = frame 1) + if ( config.timestamp_on_capture ) { - toUpld=true; - char tmbuf[64], buf[64]; - strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d-%H-%M-%S", localtime(&(timestamp.tv_sec))); - snprintf(buf, sizeof buf, "%s-%06d", tmbuf,(int)(timestamp.tv_usec)); - snprintf(UpldFile, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg_saving",UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); - snprintf(UpldFileRename, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg", UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); - } - - Image* ImgToWrite; - Image ts_image( *image ); - - if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. - { - monitor->TimestampImage( &ts_image, ×tamp ); - ImgToWrite=&ts_image; - } - else - ImgToWrite=image; - - if ( !config.opt_frame_server || !SendFrameImage( ImgToWrite, alarm_frame) ) - { - int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use - ImgToWrite->WriteJpeg( event_file, thisquality, timestamp ); - if(toUpld) - { // Because these are for real-time use and may be grabbed as they are being written, write under one name then rename - ImgToWrite->WriteJpeg(UpldFile, thisquality, timestamp); - if(rename(UpldFile, UpldFileRename)!=0) - Error ("Failure to rename real time capture file %s to %s, ignored",UpldFile, UpldFileRename); + if ( !config.opt_frame_server || !SendFrameImage( image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + image->WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + image->WriteJpeg( event_file ); + } + } + else + { + Image ts_image( *image ); + monitor->TimestampImage( &ts_image, ×tamp ); + if ( !config.opt_frame_server || !SendFrameImage( &ts_image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + ts_image.WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + ts_image.WriteJpeg( event_file ); } } - return( true ); } @@ -907,7 +885,7 @@ void EventStream::processCommand( const CmdMsg *msg ) } // If we are in single event mode and at the last frame, replay the current event - if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) + if ( (mode == MODE_SINGLE) && (curr_frame_id == event_data->frame_count) ) curr_frame_id = 1; replay_rate = ZM_RATE_BASE; diff --git a/src/zm_event.h b/src/zm_event.h index 412baa0bb..f50a5bf06 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -59,12 +59,6 @@ protected: protected: static int sd; -private: - int UpldCount; - char UpldPath[PATH_MAX]; - int UpldWriteEvery; - int UpldWriteEveryAlarm; - public: typedef std::set StringSet; typedef std::map StringSetMap; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index c1e91a00d..8f91ab28b 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -787,22 +787,7 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int return( true ); } -// Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults. - -bool Image::WriteJpeg( const char *filename, int quality_override) const -{ - return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); -} -bool Image::WriteJpeg( const char *filename) const -{ - return Image::WriteJpeg(filename, 0, (timeval){0,0}); -} -bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const -{ - return Image::WriteJpeg(filename,0,timestamp); -} - -bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const +bool Image::WriteJpeg( const char *filename, int quality_override ) const { if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { @@ -810,6 +795,7 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); return( temp_image.WriteJpeg( filename, quality_override ) ); } + int quality = quality_override?quality_override:config.jpeg_file_quality; struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; @@ -901,30 +887,6 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); } - if(timestamp.tv_sec) - { - #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds - #define EXIFTIMES_MS_LEN 0x03 - #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes - #define EXIFTIMES_LEN 0x13 // = 19 - #define EXIF_CODE 0xE1 - - char timebuf[64], msbuf[64]; - strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); - snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it - unsigned char exiftimes[82] = { - 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, - 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00 }; - memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); - memcpy(&exiftimes[EXIFTIMES_MS_OFFSET],msbuf ,EXIFTIMES_MS_LEN); // first character after the decimal point - jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); - - } - JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) diff --git a/src/zm_image.h b/src/zm_image.h index a48fafacc..46c7a031b 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -204,12 +204,7 @@ public: bool WriteRaw( const char *filename ) const; bool ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder); - - bool WriteJpeg ( const char *filename) const; - bool WriteJpeg ( const char *filename, int quality_override ) const; - bool WriteJpeg ( const char *filename, struct timeval timestamp ) const; - bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const; - + bool WriteJpeg( const char *filename, int quality_override=0 ) const; bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder); bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const; From 9e81eaa0f9fe35ffc89ea0cbbb0751f92c23e304 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:19:40 -0400 Subject: [PATCH 004/105] Remove unexpected files that were added - 3 --- web/api/app/Config/core.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 59d72162c..93dcff772 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,12 +222,12 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', 'olX2TOlboOnC474y3Tk4W4JOyuirw1EaadeHCcr4'); + Configure::write('Security.salt', '02670120062639232092038865362'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ - Configure::write('Security.cipherSeed', '84684583012508019120061282965'); + Configure::write('Security.cipherSeed', '02670120062639232092038865362'); /** * Apply timestamps with the last modified time to static assets (js, css, images). From e967e3de6efacb4e8ec84abba87c2aac349198c7 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:20:40 -0400 Subject: [PATCH 005/105] Remove unexpected files that were added - 4 --- web/api/app/Config/core.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 93dcff772..436cf8d60 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,7 +222,7 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', '02670120062639232092038865362'); + Configure::write('Security.salt', 'Q0MjGG2xRQEhJVQR85WhFJKI7f2St8RYMlVR7GNQ'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. From a091ad16f30ed2401c65d620d45abc0d4705aba1 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:36:21 -0400 Subject: [PATCH 006/105] Final cleanup before pull request --- web/skins/classic/views/montagereview.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index d243c3949..210ccc668 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -21,11 +21,10 @@ // Montage Review -- show all (visible) monitors, and allow to review time ranges easily for all monitors. // -// This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors +// This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors' images. // It also will do a pseudo play function (one second or more at a time, not less than 1 second resolution) // -// This is very much a preliminary version, very lightly tested, mostly on Firefox, but should work on IE and Chrome (at least) // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate // change the playback slider to 0 and then it does not try to play at the same time it is scrubbing. // @@ -58,7 +57,7 @@ else } // Note that this finds incomplete events as well, and any frame records written, but still cannot "see" to the end frame -// if the bulk record has not been written - to get more current reduce bulk frame sizes +// if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large) $eventsSql = " select E.Id,E.Name,E.StartTime,max(F.TimeStamp) as CalcEndTime,E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId @@ -73,7 +72,7 @@ $frameSql = " inner join Frames as F on (F.EventId = E.Id) where not isnull(StartTime) and F.Score>0 "; -// This program only calls itself with the time range involved -- it does all monitors (the user can see) all the time +// This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time if ( !empty($user['MonitorIds']) ) { @@ -248,7 +247,8 @@ else $maxTimeSecs = strtotime($maxTime); } -// If we had any alarms in those events, this builds the list of all alarm frames (thought for later - should these be ranges, so as to minimize list if very long?) +// If we had any alarms in those events, this builds the list of all alarm frames +// thought for later in case people have a LOT of alarms - change these to ranges, built as it loads, so as to minimize list length echo "var frameMonitorId = [];\n"; echo "var frameTimeStampSecs = [];\n"; From 3e85d57710440729a830b20cc9fd663aaa0a2cd5 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 30 Jul 2015 12:06:52 -0400 Subject: [PATCH 007/105] New version with added live view --- web/skins/classic/views/montagereview.php | 356 +++++++++++++++------- 1 file changed, 251 insertions(+), 105 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 210ccc668..92c15e43c 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -17,12 +17,13 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // + // --------------------- // Montage Review -- show all (visible) monitors, and allow to review time ranges easily for all monitors. // // This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors' images. -// It also will do a pseudo play function (one second or more at a time, not less than 1 second resolution) +// It also will do a pseudo play function from history, as well as a live display of images. // // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate @@ -38,6 +39,13 @@ // - Removed range from/to labels on very small graphs to keep from overlapping slider // - Changed initial (from other page) position of slider to be in the middle to be more obvious // +// Jul 29 2015 update +// - Add live mode shots from cameras via single frame pull mode +// - Added dynamic refresh rate based on how fast we can upload images +// - Closed some gaps in playback frames due to time rounding in retrieval. +// - Consolidated frame in-memory records to contiguous time rather than individual frame-seconds (still requires a good deal of browser memory) +// - Took out a lot of the integral second rounding so that it works better at subsequent replay speeds +// if ( !canView( 'Events' ) ) { $view = "error"; @@ -60,14 +68,15 @@ else // if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large) $eventsSql = " - select E.Id,E.Name,E.StartTime,max(F.TimeStamp) as CalcEndTime,E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId + select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId from Events as E inner join Monitors as M on (E.MonitorId = M.Id) inner join Frames F on F.EventId=E.Id where not isnull(E.Frames) and not isnull(StartTime) "; +// Note that the delta value seems more accurate than the time stamp for some reason. $frameSql = " - select E.Id as EventId, E.MonitorId, F.TimeStamp, max(F.Score) as Score + select E.Id as EventId, E.MonitorId, UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval Delta Second)) as TimeStampSecs, max(F.Score) as Score from Events as E inner join Frames as F on (F.EventId = E.Id) where not isnull(StartTime) and F.Score>0 "; @@ -84,6 +93,7 @@ if ( !empty($user['MonitorIds']) ) } // Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. +// Live overrides all the min/max stuff but it is still processed if ( isset($_REQUEST['minTime']) ) $minTime = validHtmlStr($_REQUEST['minTime']); @@ -104,6 +114,10 @@ else if (isset($_REQUEST['current']) ) $defaultCurrentTime=validHtmlStr($_REQUEST['current']); +$initialModeIsLive=0; +if(isset($_REQUEST['live']) ) + $initialModeIsLive=1; + $archive=1; if (isset($_REQUEST['archive']) ) $archive=validHtmlStr($_REQUEST['archive']); @@ -117,9 +131,10 @@ $eventsSql .= "group by E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.C if( isset($minTime) && isset($maxTime) ) { - $eventsSql .= "having CalcEndTime > '" . $minTime . "' and StartTime < '" . $maxTime . "'"; - $frameSql .= " - and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); + $eventsSql .= "having CalcEndTimeSecs > '" . $minTimeSecs . "' and StartTimeSecs < '" . $maxTimeSecs . "'"; + $frameSql .= "and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; } $frameSql .= "group by E.Id, E.MonitorId, F.TimeStamp order by E.MonitorId, F.TimeStamp asc"; @@ -146,19 +161,20 @@ input[type=range]::-ms-tooltip { step=0.10 width=20% onchange='changescale(this.value)'/> x
-
+
step=1 wdth=20% onchange='changespeed(this.value)'/> - x + fps
- - - - - - - + + + + + + + +
@@ -168,9 +184,34 @@ input[type=range]::-ms-tooltip {
- + + +\n"; - +echo "
\n"; foreach ($monitors as $m) { if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events @@ -337,6 +360,8 @@ foreach ($monitors as $m) echo "No Canvas Support!!\n"; } } +echo "
\n"; +echo "

evaluating fps

\n"; echo "\n"; -echo "
\n"; -foreach ($monitors as $m) -{ - if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events - { - echo "No Canvas Support!!\n"; - } -} -echo "
\n"; -echo "

evaluating fps

\n"; -echo "
- - From e7264a8167059bee96f2e700403e0aa95ff57fcb Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Mon, 3 Aug 2015 15:31:13 -0400 Subject: [PATCH 010/105] Minox fixes, make live mode default, 1 hour default --- web/skins/classic/views/montagereview.php | 45 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index eb9760c02..2ee386428 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -26,6 +26,25 @@ // It also will do a pseudo play function from history, as well as a live display of images. // +// Valid query string: +// +// &maxTime, minTime = string formats (locale) of starting and ending time for history (pass both or none), default = last hour +// +// ¤t = string format of time, where the slider is positioned first in history mode (normally only used in reloads, default = half scale) +// +// &speed = one of the valid speeds below (see $speeds in php section, default = 1.0) +// +// &scale = image sie scale (.1 to 1.0, or 1.1 = fit, default = fit) +// +// &live=1 whether to start in live mode, 1 = yes, 0 = no +// +// &archive = if "1" then include archive frames, if "0" do not, default "1" +// +// &z1, &z2, etc. = initial monitor specific zoom, numeral is a monitor id, default = 1.0, used in page reloads normally +// +// &group = group number of monitors to display, comes from console if set, default is none (i.e. not limited by group) +// + // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate // change the playback slider to 0 and then it does not try to play at the same time it is scrubbing. // @@ -56,6 +75,8 @@ // - Add max fit, make it default // - Remove timeline in live mode, and restore when switched back (live button becomes toggle) // - Add +/- zooms to individual monitors so you can adjust size, persist across reload buttons (only) +// - Change default to 1 hour and live mode (reduce workload on initial load, let people ask for huge history amounts) +// - Since this may be run as a standalone window for shortcuts, etc., add a "console" link to get back to the console // if ( !canView( 'Events' ) ) { @@ -107,12 +128,21 @@ if ( !empty($user['MonitorIds']) ) // Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. // Live overrides all the min/max stuff but it is still processed +// The default (nothing at all specified) is for 1 hour so we do not read the whole database + + +if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) +{ + $maxTime=strftime("%c",time()); + $minTime=strftime("%c",time() - 3600); +} if ( isset($_REQUEST['minTime']) ) $minTime = validHtmlStr($_REQUEST['minTime']); if ( isset($_REQUEST['maxTime']) ) $maxTime = validHtmlStr($_REQUEST['maxTime']); + if ( isset($_REQUEST['scale']) ) $defaultScale=validHtmlStr($_REQUEST['scale']); else @@ -137,9 +167,9 @@ if (isset($_REQUEST['current']) ) $defaultCurrentTime=validHtmlStr($_REQUEST['current']); -$initialModeIsLive=0; -if(isset($_REQUEST['live']) ) - $initialModeIsLive=1; +$initialModeIsLive=1; +if(isset($_REQUEST['live']) && $_REQUEST['live']=='0' ) + $initialModeIsLive=0; $initialDisplayInterval=1000; if(isset($_REQUEST['displayinterval'])) @@ -192,6 +222,7 @@ input[type=range]::-ms-tooltip {