Merge branch 'release-1.36' of github.com:ZoneMinder/zoneminder into release-1.36
This commit is contained in:
commit
7f8195b248
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -377,9 +377,10 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval ×tamp) {
|
||||||
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 ×tamp) {
|
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]);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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++ ) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -63,13 +63,13 @@ function processRows(rows) {
|
||||||
|
|
||||||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
||||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + row.Name + '</a>' +
|
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&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&eid=' + eid + '">' + row.Monitor + '</a>';
|
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=event&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&eid=' + eid + '">' + row.Frames + '</a>';
|
row.Frames = '<a href="?view=frames&eid=' + eid + '">' + row.Frames + '</a>';
|
||||||
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue