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

This commit is contained in:
Isaac Connor 2021-11-29 13:59:24 -05:00
commit 7f8195b248
12 changed files with 68 additions and 40 deletions

View File

@ -4,7 +4,7 @@ Debian
.. contents:: .. contents::
Easy Way: Debian 11 (Bullseye) Easy Way: Debian 11 (Bullseye)
------------------------ ------------------------------
This procedure will guide you through the installation of ZoneMinder on Debian 11 (Bullseye). This procedure will guide you through the installation of ZoneMinder on Debian 11 (Bullseye).
@ -104,7 +104,7 @@ Add the following to the /etc/apt/sources.list.d/zoneminder.list file
You can do this using: 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 echo "deb https://zmrepo.zoneminder.com/debian/release-1.36 buster/" | sudo tee /etc/apt/sources.list.d/zoneminder.list

View File

@ -230,8 +230,8 @@ sub Sql {
# PostCondition, so no further SQL # PostCondition, so no further SQL
} else { } else {
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/; ( 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' ) { if ( $term->{attr} eq 'AlarmedZoneId' ) {
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND Score > 0 AND ZoneId='.$value.')'; $value = '(SELECT * FROM Stats WHERE EventId=E.Id AND Score > 0 AND ZoneId='.$value.')';
} elsif ( $term->{attr} =~ /^MonitorName/ ) { } elsif ( $term->{attr} =~ /^MonitorName/ ) {
@ -250,7 +250,8 @@ sub Sql {
$$self{Server} = new ZoneMinder::Server($temp_value); $$self{Server} = new ZoneMinder::Server($temp_value);
} }
} elsif ( $term->{attr} eq 'StorageId' ) { } 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); $$self{Storage} = new ZoneMinder::Storage($temp_value);
} elsif ( $term->{attr} eq 'Name' } elsif ( $term->{attr} eq 'Name'
|| $term->{attr} eq 'Cause' || $term->{attr} eq 'Cause'

View File

@ -429,10 +429,20 @@ sub start {
# It's not running, or at least it's not been started by us # It's not running, or at least it's not been started by us
$process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef }; $process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef };
} elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) { } 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})) .strftime('%y/%m/%d %H:%M:%S', localtime($process->{started}))
.", pid = $process->{pid}\n" .", pid = $process->{pid}\n"
); );
}
return; return;
} }
@ -523,7 +533,7 @@ sub send_stop {
."\n" ."\n"
); );
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n"; sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return(); return ();
} }
my $pid = $process->{pid}; my $pid = $process->{pid};
@ -586,7 +596,7 @@ sub check_for_processes_to_kill {
sub stop { sub stop {
my ( $daemon, @args ) = @_; my ( $daemon, @args ) = @_;
my $command = join(' ', $daemon, @args ); my $command = join(' ', $daemon, @args);
my $process = $cmd_hash{$command}; my $process = $cmd_hash{$command};
if ( !$process ) { if ( !$process ) {
dPrint(ZoneMinder::Logger::WARNING, "Can't find process with command of '$command'"); dPrint(ZoneMinder::Logger::WARNING, "Can't find process with command of '$command'");

View File

@ -1904,7 +1904,7 @@ bool Monitor::Analyse() {
if (snap->image) { if (snap->image) {
// decoder may not have been able to provide an image // decoder may not have been able to provide an image
if (!ref_image.Buffer()) { if (!ref_image.Buffer()) {
Debug(1, "Assigning instead of Dectecting"); Debug(1, "Assigning instead of Detecting");
ref_image.Assign(*(snap->image)); ref_image.Assign(*(snap->image));
} else { } else {
Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image); Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image);

View File

@ -377,9 +377,10 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval &timestamp) {
return false; return false;
} // end bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) } // end bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp)
bool MonitorStream::sendFrame(Image *image, const timeval &timestamp) { bool MonitorStream::sendFrame(Image *image, SystemTimePoint timestamp) {
if (!config.timestamp_on_capture) if (!config.timestamp_on_capture) {
monitor->TimestampImage(image, timestamp); monitor->TimestampImage(image, timestamp);
}
Image *send_image = prepareImage(image); Image *send_image = prepareImage(image);
fputs("--" BOUNDARY "\r\n", stdout); 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; 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); Debug(1, "write index: %d %d", monitor->shared_data->last_write_index, index);
Image *snap_image = monitor->image_buffer[index]; Image *snap_image = monitor->image_buffer[index];
if (!config.timestamp_on_capture) {
monitor->TimestampImage(snap_image,
SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index])));
}
if (!config.timestamp_on_capture) { if (!config.timestamp_on_capture) {
monitor->TimestampImage(snap_image, monitor->shared_timestamps[index]); monitor->TimestampImage(snap_image, monitor->shared_timestamps[index]);

View File

@ -116,14 +116,15 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
, max_video_packet_count); , max_video_packet_count);
for ( for (
auto it = ++pktQueue.begin(); auto it = ++pktQueue.begin();
it != pktQueue.end() and *it != add_packet; it != pktQueue.end() and *it != add_packet;
// iterator is incremented by erase
) { ) {
std::shared_ptr <ZMPacket>zm_packet = *it; std::shared_ptr <ZMPacket>zm_packet = *it;
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
if (!lp->trylock()) { 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; delete lp;
++it; ++it;
continue; continue;
@ -312,7 +313,6 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
pktQueue.size()); pktQueue.size());
pktQueue.pop_front(); pktQueue.pop_front();
packet_counts[zm_packet->packet.stream_index] -= 1; packet_counts[zm_packet->packet.stream_index] -= 1;
//delete zm_packet;
} }
} // end if have at least max_video_packet_count video packets remaining } // end if have at least max_video_packet_count video packets remaining
// We signal on every packet because someday we may analyze sound // We signal on every packet because someday we may analyze sound

View File

@ -874,16 +874,23 @@ std::vector<Zone> Zone::Load(Monitor *monitor) {
continue; continue;
} }
if (polygon.Extent().Lo().x_ < 0 || polygon.Extent().Hi().x_ > static_cast<int32>(monitor->Width()) if (polygon.Extent().Lo().x_ < 0
|| polygon.Extent().Lo().y_ < 0 || polygon.Extent().Hi().y_ > static_cast<int32>(monitor->Height())) { ||
Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), fixing", polygon.Extent().Hi().x_ > static_cast<int32>(monitor->Width())
||
polygon.Extent().Lo().y_ < 0
||
polygon.Extent().Hi().y_ > static_cast<int32>(monitor->Height())) {
Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d) != (%d,%d), fixing",
Id, Id,
Name, Name,
monitor->Name(), monitor->Name(),
polygon.Extent().Lo().x_, polygon.Extent().Lo().x_,
polygon.Extent().Lo().y_, polygon.Extent().Lo().y_,
polygon.Extent().Hi().x_, polygon.Extent().Hi().x_,
polygon.Extent().Hi().y_); polygon.Extent().Hi().y_,
monitor->Width(),
monitor->Height());
polygon.Clip(Box( polygon.Clip(Box(
{0, 0}, {0, 0},

View File

@ -152,7 +152,7 @@ $booleanValues = array(
$focusWindow = true; $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(); $weekdays = array();
for ( $i = 0; $i < 7; $i++ ) { for ( $i = 0; $i < 7; $i++ ) {

View File

@ -773,8 +773,9 @@ function manageDelConfirmModalBtns() {
return; return;
} }
pauseClicked();
evt.preventDefault(); 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) { .done(function(data) {
$j('#deleteConfirm').modal('hide'); $j('#deleteConfirm').modal('hide');
streamNext(true); streamNext(true);

View File

@ -63,13 +63,13 @@ function processRows(rows) {
row.Id = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + eid + '</a>'; row.Id = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + eid + '</a>';
row.Name = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.Name + '</a>' + row.Name = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.Name + '</a>' +
'<br/><div class="small text-nowrap text-muted">' + archived + emailed + '</div>'; '<br/><div class="small text-muted">' + archived + emailed + '</div>';
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=event&amp;eid=' + eid + '">' + row.Monitor + '</a>'; if ( canEdit.Monitors ) row.Monitor = '<a href="?view=event&amp;eid=' + eid + '">' + row.Monitor + '</a>';
if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>'; if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
if ( row.Notes.indexOf('detected:') >= 0 ) { if ( row.Notes.indexOf('detected:') >= 0 ) {
row.Cause = row.Cause + '<a href="#" class="objDetectLink" data-eid=' +eid+ '><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></div></a>'; row.Cause = row.Cause + '<a href="#" class="objDetectLink" data-eid=' +eid+ '><div class="small text-muted"><u>' + row.Notes + '</u></div></div></a>';
} else if ( row.Notes != 'Forced Web: ' ) { } else if ( row.Notes != 'Forced Web: ' ) {
row.Cause = row.Cause + '<br/><div class="small text-nowrap text-muted">' + row.Notes + '</div>'; row.Cause = row.Cause + '<br/><div class="small text-muted">' + row.Notes + '</div>';
} }
row.Frames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.Frames + '</a>'; row.Frames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.Frames + '</a>';
row.AlarmFrames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.AlarmFrames + '</a>'; row.AlarmFrames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.AlarmFrames + '</a>';

View File

@ -57,7 +57,7 @@ function getFrame(monId, time, last_Frame) {
var events_for_monitor = events_by_monitor_id[monId]; var events_for_monitor = events_by_monitor_id[monId];
if ( !events_for_monitor ) { if ( !events_for_monitor ) {
console.log("No events for monitor " + monId); //console.log("No events for monitor " + monId);
return; return;
} }
@ -648,8 +648,11 @@ function setSpeed(speed_index) {
} }
function setLive(value) { 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; liveMode = value;
var form = $j('#montagereview_form')[0]; var form = document.getElementById('montagereview_form');
form.elements['live'].value = value; form.elements['live'].value = value;
form.submit(); form.submit();
return false; return false;
@ -985,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 ) { for ( var i = 0, len = monitorPtr.length; i < len; i += 1 ) {
var monId = monitorPtr[i]; var monId = monitorPtr[i];
if ( !monId ) continue; if ( !monId ) continue;
@ -1006,18 +1022,6 @@ function initPage() {
} }
} // end foreach monitor } // 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); setSpeed(speedIndex);
//setFit(fitMode); // will redraw //setFit(fitMode); // will redraw
//setLive(liveMode); // will redraw //setLive(liveMode); // will redraw

View File

@ -239,6 +239,6 @@ echo "];\n";
var cWidth; // save canvas width var cWidth; // save canvas width
var cHeight; // save canvas height var cHeight; // save canvas height
var canvas; // global canvas definition so we don't have to keep looking it up 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 underSlider; // use this to hold what is hidden by the slider
var underSliderX; // Where the above was taken from (left side, Y is zero) var underSliderX; // Where the above was taken from (left side, Y is zero)