From c14d7889a505e702e5ef75adee0ed74873956c64 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 29 Nov 2021 13:48:44 -0500 Subject: [PATCH 01/13] Fix task=>action so that deleting works. Pause streaming before delete to prevent errors being logged due to missing files --- web/skins/classic/views/js/event.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 05914f911..94e132cc1 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -773,8 +773,9 @@ function manageDelConfirmModalBtns() { return; } + pauseClicked(); evt.preventDefault(); - $j.getJSON(thisUrl + '?request=event&task=delete&id='+eventData.Id) + $j.getJSON(thisUrl + '?request=event&action=delete&id='+eventData.Id) .done(function(data) { $j('#deleteConfirm').modal('hide'); streamNext(true); From 4ef5056a911536e1cffcfba2836c1092ccf5c504 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 27 Nov 2021 19:16:32 -0500 Subject: [PATCH 02/13] fix by removing code block --- docs/installationguide/debian.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index ea5fbeda1..82c9eb132 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -104,7 +104,7 @@ Add the following to the /etc/apt/sources.list.d/zoneminder.list file You can do this using: -.. code-block:: +:: echo "deb https://zmrepo.zoneminder.com/debian/release-1.36 buster/" | sudo tee /etc/apt/sources.list.d/zoneminder.list From eeb655fd7701ebb6fafd6685167d150db61e7985 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 27 Nov 2021 19:10:09 -0500 Subject: [PATCH 03/13] Fix underline --- docs/installationguide/debian.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index 82c9eb132..8346abe00 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -4,7 +4,7 @@ Debian .. contents:: Easy Way: Debian 11 (Bullseye) ------------------------- +------------------------------ This procedure will guide you through the installation of ZoneMinder on Debian 11 (Bullseye). From 4030fa8bc47125e6dcc3b038156d4d2644bc2476 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 26 Nov 2021 10:35:15 -0500 Subject: [PATCH 04/13] Fix NULL and add special 0 case for Storage area specification in filter --- web/skins/classic/views/filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index b425f7896..b441db349 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -152,7 +152,7 @@ $booleanValues = array( $focusWindow = true; -$storageareas = array('' => 'All') + ZM\ZM_Object::Objects_Indexed_By_Id('ZM\Storage'); +$storageareas = array('' => array('Name'=>'NULL Unspecified'), '0' => array('Name'=>'Zero')) + ZM\ZM_Object::Objects_Indexed_By_Id('ZM\Storage'); $weekdays = array(); for ( $i = 0; $i < 7; $i++ ) { From 765886ae729e6baca0ce5078aa1e476496dd435f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 26 Nov 2021 10:31:54 -0500 Subject: [PATCH 05/13] Handle bug where a value of '' will prevent special case handling. Allow '' to mean NULL when specifying Storage Area --- scripts/ZoneMinder/lib/ZoneMinder/Filter.pm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index 3a3308938..0db46ff0d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -230,8 +230,8 @@ sub Sql { # PostCondition, so no further SQL } else { ( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/; - foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) { - + # Empty value will result in () from split + foreach my $temp_value ( $stripped_value ? split( /["'\s]*?,["'\s]*?/, $stripped_value ) : $stripped_value ) { if ( $term->{attr} eq 'AlarmedZoneId' ) { $value = '(SELECT * FROM Stats WHERE EventId=E.Id AND Score > 0 AND ZoneId='.$value.')'; } elsif ( $term->{attr} =~ /^MonitorName/ ) { @@ -250,7 +250,8 @@ sub Sql { $$self{Server} = new ZoneMinder::Server($temp_value); } } elsif ( $term->{attr} eq 'StorageId' ) { - $value = "'$temp_value'"; + # Empty means NULL, otherwise must be an integer + $value = $temp_value ne '' ? int($temp_value) : 'NULL'; $$self{Storage} = new ZoneMinder::Storage($temp_value); } elsif ( $term->{attr} eq 'Name' || $term->{attr} eq 'Cause' From 209d45c5f0c2c3039bf1dfa0a4bb4f1adbdeaa6b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Nov 2021 14:28:31 -0500 Subject: [PATCH 06/13] include monitor dimensions when logging about zone mismatch --- src/zm_zone.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index 41174857f..1aacacac7 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -874,16 +874,23 @@ std::vector Zone::Load(Monitor *monitor) { continue; } - if (polygon.Extent().Lo().x_ < 0 || polygon.Extent().Hi().x_ > static_cast(monitor->Width()) - || polygon.Extent().Lo().y_ < 0 || polygon.Extent().Hi().y_ > static_cast(monitor->Height())) { - Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), fixing", + if (polygon.Extent().Lo().x_ < 0 + || + polygon.Extent().Hi().x_ > static_cast(monitor->Width()) + || + polygon.Extent().Lo().y_ < 0 + || + polygon.Extent().Hi().y_ > static_cast(monitor->Height())) { + Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d) != (%d,%d), fixing", Id, Name, monitor->Name(), polygon.Extent().Lo().x_, polygon.Extent().Lo().y_, polygon.Extent().Hi().x_, - polygon.Extent().Hi().y_); + polygon.Extent().Hi().y_, + monitor->Width(), + monitor->Height()); polygon.Clip(Box( {0, 0}, From 11c12f5d1082082daca24a08b551062b6b070dac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Nov 2021 14:28:15 -0500 Subject: [PATCH 07/13] typo --- src/zm_monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 545d173d5..5d1cd1792 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1904,7 +1904,7 @@ bool Monitor::Analyse() { if (snap->image) { // decoder may not have been able to provide an image if (!ref_image.Buffer()) { - Debug(1, "Assigning instead of Dectecting"); + Debug(1, "Assigning instead of Detecting"); ref_image.Assign(*(snap->image)); } else { Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image); From 7d470fa059b165c9b73c6754229f53db66e5fb05 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Nov 2021 12:42:31 -0500 Subject: [PATCH 08/13] Code comments and make warning when the first packet in queue is locked. --- src/zm_packetqueue.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index ceef421db..8c088c1db 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -116,14 +116,15 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { , max_video_packet_count); for ( - auto it = ++pktQueue.begin(); - it != pktQueue.end() and *it != add_packet; + auto it = ++pktQueue.begin(); + it != pktQueue.end() and *it != add_packet; + // iterator is incremented by erase ) { std::shared_ptr zm_packet = *it; ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (!lp->trylock()) { - Debug(1, "Found locked packet when trying to free up video packets. Skipping to next one"); + Warning("Found locked packet when trying to free up video packets. This basically means that decoding is not keeping up."); delete lp; ++it; continue; @@ -312,7 +313,6 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { pktQueue.size()); pktQueue.pop_front(); packet_counts[zm_packet->packet.stream_index] -= 1; - //delete zm_packet; } } // end if have at least max_video_packet_count video packets remaining // We signal on every packet because someday we may analyze sound From 5adf5dab50147dd9cbcfe3d05116e9ef916a8fcd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Nov 2021 12:06:13 -0500 Subject: [PATCH 09/13] Remove text-nowrap from cause/notes column --- web/skins/classic/views/js/events.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 6139ba3e4..bafd16763 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -63,13 +63,13 @@ function processRows(rows) { row.Id = '' + eid + ''; row.Name = '' + row.Name + '' + - '
' + archived + emailed + '
'; + '
' + archived + emailed + '
'; if ( canEdit.Monitors ) row.Monitor = '' + row.Monitor + ''; if ( canEdit.Events ) row.Cause = '' + row.Cause + ''; if ( row.Notes.indexOf('detected:') >= 0 ) { - row.Cause = row.Cause + '
' + row.Notes + '
'; + row.Cause = row.Cause + '
' + row.Notes + '
'; } else if ( row.Notes != 'Forced Web: ' ) { - row.Cause = row.Cause + '
' + row.Notes + '
'; + row.Cause = row.Cause + '
' + row.Notes + '
'; } row.Frames = '' + row.Frames + ''; row.AlarmFrames = '' + row.AlarmFrames + ''; From afc21cd14db854418bf911d035f70362336b119d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 23 Nov 2021 11:05:39 -0500 Subject: [PATCH 10/13] If we are starting a process that is waiting to term, mark it to get started by the reaper. Fixes case where zmdc thought the process was still running and so didn't start it. We never noticed because zmwatch would eventually notice. The result is instant restart. --- scripts/zmdc.pl.in | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 5cf866e56..793049479 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -429,10 +429,20 @@ sub start { # It's not running, or at least it's not been started by us $process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef }; } elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) { - dPrint(ZoneMinder::Logger::INFO, "'$process->{command}' already running at " + if ($process->{term_sent_at}) { + dPrint(ZoneMinder::Logger::INFO, "'$process->{command}' was told to term at " + .strftime('%y/%m/%d %H:%M:%S', localtime($process->{term_sent_at})) + .", pid = $process->{pid}\n" + ); + $process->{keepalive} = !undef; + $process->{delay} = 0; + delete $terminating_processes{$command}; + } else { + dPrint(ZoneMinder::Logger::INFO, "'$process->{command}' already running at " .strftime('%y/%m/%d %H:%M:%S', localtime($process->{started})) .", pid = $process->{pid}\n" - ); + ); + } return; } @@ -523,7 +533,7 @@ sub send_stop { ."\n" ); sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n"; - return(); + return (); } my $pid = $process->{pid}; @@ -586,7 +596,7 @@ sub check_for_processes_to_kill { sub stop { my ( $daemon, @args ) = @_; - my $command = join(' ', $daemon, @args ); + my $command = join(' ', $daemon, @args); my $process = $cmd_hash{$command}; if ( !$process ) { dPrint(ZoneMinder::Logger::WARNING, "Can't find process with command of '$command'"); From 0f476998d40f7473327e585bce493e5a6fe768c4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 22 Nov 2021 14:17:50 -0500 Subject: [PATCH 11/13] kill the background timer when switching to history so that we don't cause a javascript error. comment out debugging and use native javascript instead of jquery. --- web/skins/classic/views/js/montagereview.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 787a910d0..813b5cc98 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -57,7 +57,7 @@ function getFrame(monId, time, last_Frame) { var events_for_monitor = events_by_monitor_id[monId]; if ( !events_for_monitor ) { - console.log("No events for monitor " + monId); + //console.log("No events for monitor " + monId); return; } @@ -648,8 +648,11 @@ function setSpeed(speed_index) { } function setLive(value) { + // When we submit the context etc goes away but we may still be trying to update + // So kill the timer. + clearInterval(timerObj); liveMode = value; - var form = $j('#montagereview_form')[0]; + var form = document.getElementById('montagereview_form'); form.elements['live'].value = value; form.submit(); return false; From 9764875449315053df92a68af3edf2a215c22003 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 22 Nov 2021 12:53:51 -0500 Subject: [PATCH 12/13] Move init of ctx up before we setup the monitors. I think in some cases we can calls functions that assume ctx has a value. Uncaught%20TypeError%3A%20Cannot%20read%20properties%20of%20undefined%20(reading%20'getImageData') --- web/skins/classic/views/js/montagereview.js | 25 ++++++++++--------- .../classic/views/js/montagereview.js.php | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 813b5cc98..60856f4ca 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -988,6 +988,19 @@ function initPage() { }); }); + if ( !liveMode ) { + canvas = document.getElementById('timeline'); + + canvas.addEventListener('mousemove', mmove, false); + canvas.addEventListener('touchmove', tmove, false); + canvas.addEventListener('mousedown', mdown, false); + canvas.addEventListener('mouseup', mup, false); + canvas.addEventListener('mouseout', mout, false); + + ctx = canvas.getContext('2d'); + drawGraph(); + } + for ( var i = 0, len = monitorPtr.length; i < len; i += 1 ) { var monId = monitorPtr[i]; if ( !monId ) continue; @@ -1009,18 +1022,6 @@ function initPage() { } } // end foreach monitor - if ( !liveMode ) { - canvas = document.getElementById('timeline'); - - canvas.addEventListener('mousemove', mmove, false); - canvas.addEventListener('touchmove', tmove, false); - canvas.addEventListener('mousedown', mdown, false); - canvas.addEventListener('mouseup', mup, false); - canvas.addEventListener('mouseout', mout, false); - - ctx = canvas.getContext('2d'); - drawGraph(); - } setSpeed(speedIndex); //setFit(fitMode); // will redraw //setLive(liveMode); // will redraw diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index d82f103ed..f4b6222f4 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -239,6 +239,6 @@ echo "];\n"; var cWidth; // save canvas width var cHeight; // save canvas height var canvas; // global canvas definition so we don't have to keep looking it up -var ctx; +var ctx = null; var underSlider; // use this to hold what is hidden by the slider var underSliderX; // Where the above was taken from (left side, Y is zero) From 59e8bca3bcd031e130fcc4174e2af295b300dbd5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 19 Nov 2021 11:59:19 -0500 Subject: [PATCH 13/13] timestamp image before scaling. Fixes lack of scaling when TIMESTAMP_ON_CAPTURE is off --- src/zm_monitorstream.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 126ed708e..5d7309435 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -377,9 +377,10 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval ×tamp) { return false; } // end bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) -bool MonitorStream::sendFrame(Image *image, const timeval ×tamp) { - if (!config.timestamp_on_capture) +bool MonitorStream::sendFrame(Image *image, SystemTimePoint timestamp) { + if (!config.timestamp_on_capture) { monitor->TimestampImage(image, timestamp); + } Image *send_image = prepareImage(image); fputs("--" BOUNDARY "\r\n", stdout); @@ -863,6 +864,10 @@ void MonitorStream::SingleImage(int scale) { int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; Debug(1, "write index: %d %d", monitor->shared_data->last_write_index, index); Image *snap_image = monitor->image_buffer[index]; + if (!config.timestamp_on_capture) { + monitor->TimestampImage(snap_image, + SystemTimePoint(zm::chrono::duration_cast(monitor->shared_timestamps[index]))); + } if (!config.timestamp_on_capture) { monitor->TimestampImage(snap_image, monitor->shared_timestamps[index]);