Merge branch 'release-1.36' of github.com:ZoneMinder/zoneminder into release-1.36
This commit is contained in:
commit
7517bdc6ec
|
@ -2,7 +2,7 @@
|
|||
|
||||
github: [connortechnology,pliablepixels] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: zoneminder # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
open_collective: zoneminder # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
|
|
|
@ -9,7 +9,7 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-16.04
|
||||
runs-on: zm-xenial-ci
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
default:
|
||||
image:
|
||||
name: ubuntu:latest
|
||||
before_script:
|
||||
- apt-get update -yq
|
||||
- DEBIAN_FRONTEND=noninteractive apt-get install -yq devscripts sudo
|
||||
|
||||
deb:
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
script:
|
||||
- yes "" | ./utils/do_debian_package.sh --snapshot=stable --type=binary --interactive=no --dput=no --debbuild-extra=--no-sign || true
|
||||
artifacts:
|
||||
paths:
|
||||
- '*.deb'
|
||||
expire_in: 1 week
|
|
@ -30,7 +30,7 @@ This is the recommended method to install ZoneMinder onto your system. ZoneMinde
|
|||
- Debian from their [default repository](https://packages.debian.org/search?searchon=names&keywords=zoneminder)
|
||||
- RHEL/CentOS and clones via [RPM Fusion](http://rpmfusion.org)
|
||||
- Fedora via [RPM Fusion](http://rpmfusion.org)
|
||||
- OpenSuse via [third party repository](http://www.zoneminder.com/wiki/index.php/Installing_using_ZoneMinder_RPMs_for_SuSE)
|
||||
- OpenSuse via [third party repository](https://wiki.zoneminder.com/Installing_using_ZoneMinder_RPMs_for_SuSE)
|
||||
- Mageia from their default repository
|
||||
- Arch via the [AUR](https://aur.archlinux.org/packages/zoneminder/)
|
||||
- Gentoo via [Portage Overlays](http://gpo.zugaina.org/www-misc/zoneminder)
|
||||
|
|
|
@ -539,7 +539,7 @@ CREATE TABLE `Monitors` (
|
|||
`Longitude` DECIMAL(11,8),
|
||||
`RTSPServer` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`RTSPStreamName` varchar(255) NOT NULL default '',
|
||||
`Importance` enum('Not','Less','Normal'),
|
||||
`Importance` enum('Normal','Less','Not') NOT NULL default 'Normal',
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
UPDATE Monitors set Importance = 'Normal' where Importance IS NULL;
|
||||
ALTER TABLE `Monitors` MODIFY `Importance` enum('Normal','Less','Not') NOT NULL default 'Normal';
|
|
@ -36,7 +36,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.36.5
|
||||
Version: 1.36.9
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
@ -430,6 +430,18 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zonemin
|
|||
%dir %attr(755,nginx,nginx) %{_localstatedir}/log/zoneminder
|
||||
|
||||
%changelog
|
||||
* Tue Oct 19 2021 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.36.9-1
|
||||
- 1.36.9 release
|
||||
|
||||
* Wed Oct 06 2021 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.36.8-1
|
||||
- 1.36.8 release
|
||||
|
||||
* Mon Sep 13 2021 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.36.7-1
|
||||
- 1.36.7 release
|
||||
|
||||
* Wed Sep 08 2021 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.36.6-1
|
||||
- 1.36.6 release
|
||||
|
||||
* Tue Jun 22 2021 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.36.5-1
|
||||
- 1.36.5 release
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ change the 3 to a 1
|
|||
|
||||
I can't see more than 6 monitors in montage on my browser
|
||||
---------------------------------------------------------
|
||||
Browsers such a Chrome and Safari only support upto 6 streams from the same domain. To work around that, take a look at the multi-port configuration discussed in the ``MIN_STREAMING_PORT`` configuration in :doc:`/userguide/options/options_network`
|
||||
Browsers such a Chrome and Safari only support up to 6 streams from the same domain. To work around that, take a look at the multi-port configuration discussed in the ``MIN_STREAMING_PORT`` configuration in :doc:`/userguide/options/options_network`
|
||||
|
||||
Why is ZoneMinder using so much CPU?
|
||||
---------------------------------------
|
||||
|
|
|
@ -56,13 +56,13 @@ Add the following to the /etc/apt/sources.list.d/zoneminder.list file
|
|||
::
|
||||
|
||||
# ZoneMinder repository
|
||||
deb https://zmrepo.zoneminder.com/debian/release-1.34 buster/
|
||||
deb https://zmrepo.zoneminder.com/debian/release-1.36 buster/
|
||||
|
||||
You can do this using:
|
||||
|
||||
.. code-block::
|
||||
|
||||
echo "deb https://zmrepo.zoneminder.com/debian/release-1.34 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
|
||||
|
||||
Because ZoneMinder's package repository provides a secure connection through HTTPS, apt must be enabled for HTTPS.
|
||||
::
|
||||
|
@ -158,7 +158,7 @@ You are now ready to go with ZoneMinder. Open a browser and type either ``localh
|
|||
Easy Way: Debian Stretch
|
||||
------------------------
|
||||
|
||||
This procedure will guide you through the installation of ZoneMinder on Debian 9 (Stretch). This section has been tested with ZoneMinder 1.34 on Debian 9.8.
|
||||
This procedure will guide you through the installation of ZoneMinder on Debian 9 (Stretch). This section has been tested with ZoneMinder 1.36 on Debian 9.8.
|
||||
|
||||
**Step 1:** Make sure your system is up to date
|
||||
|
||||
|
@ -204,7 +204,7 @@ Add the following to the bottom of the file
|
|||
::
|
||||
|
||||
# ZoneMinder repository
|
||||
deb https://zmrepo.zoneminder.com/debian/release-1.34 stretch/
|
||||
deb https://zmrepo.zoneminder.com/debian/release-1.36 stretch/
|
||||
|
||||
CTRL+o and <Enter> to save
|
||||
CTRL+x to exit
|
||||
|
|
|
@ -41,7 +41,7 @@ guide you with a quick search.
|
|||
|
||||
::
|
||||
|
||||
add-apt-repository ppa:iconnor/zoneminder-1.34
|
||||
add-apt-repository ppa:iconnor/zoneminder-1.36
|
||||
|
||||
Update repo and upgrade.
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ Source Path
|
|||
Use this field to enter the full URL of the stream or file your camera supports. This is usually an RTSP url. There are several methods to learn this:
|
||||
|
||||
* Check the documentation that came with your camera
|
||||
* Look for your camera in the hardware compatibilty list in the `hardware compatibility wiki <https://wiki.zoneminder.com/Hardware_Compatibility_List>`__
|
||||
* Look for your camera in the hardware compatibility list in the `hardware compatibility wiki <https://wiki.zoneminder.com/Hardware_Compatibility_List>`__
|
||||
* Try ZoneMinder's new ONVIF probe feature
|
||||
* Download and install the `ONVIF Device Manager <https://sourceforge.net/projects/onvifdm/>`__ onto a Windows machine
|
||||
* Use Google to find third party sites, such as ispy, which document this information
|
||||
|
@ -179,12 +179,12 @@ Storage Tab
|
|||
The storage section allows for each monitor to configure if and how video and audio are recorded.
|
||||
|
||||
Save JPEGs
|
||||
Records video in individual JPEG frames. Storing JPEG frames requires more storage space than h264 but it allows to view an event anytime while it is being recorded.
|
||||
Records video in individual JPEG frames. Storing JPEG frames requires more storage space than h264 but it allows one to view an event anytime while it is being recorded.
|
||||
|
||||
* Disabled – video is not recorded as JPEG frames. If this setting is selected, then "Video Writer" should be enabled otherwise there is no video recording at all.
|
||||
* Frames only – video is recorded in individual JPEG frames.
|
||||
* Analysis images only (if available) – video is recorded in invidual JPEG frames with an overlay of the motion detection analysis information. Note that this overlay remains permanently visible in the frames.
|
||||
* Frames + Analysis images (if available) – video is recorded twice, once as normal individual JPEG frames and once in invidual JPEG frames with analysis information overlaid.
|
||||
* Analysis images only (if available) – video is recorded in individual JPEG frames with an overlay of the motion detection analysis information. Note that this overlay remains permanently visible in the frames.
|
||||
* Frames + Analysis images (if available) – video is recorded twice, once as normal individual JPEG frames and once in individual JPEG frames with analysis information overlaid.
|
||||
|
||||
Video Writer
|
||||
Records video in real video format. It provides much better compression results than saving JPEGs, thus longer video history can be stored.
|
||||
|
|
|
@ -34,7 +34,7 @@ Here is what the filter window looks like
|
|||
* Update used disk space: calculates how much disk space is currently taken by the event and updates the db record.
|
||||
* Create video for all matches: creates a video file of all the events that match
|
||||
* Create video for all matches: ffmpeg will be used to create a video file (mp4) out of all the stored jpgs if using jpeg storage.
|
||||
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events. You can use replacement tokens as subsequent arguents to the command, the last argument will be the absolute path to the event, preceeded by replacement arguents. eg: /usr/bin/script.sh %MN% will excecute as /usr/bin/script.sh MonitorName /path/to/event. Please note that urls may contain characters like & that need quoting. So you may need to put quotes around them like /usr/bin/scrupt.sh "%MN%".
|
||||
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events. You can use replacement tokens as subsequent arguents to the command, the last argument will be the absolute path to the event, preceded by replacement arguents. eg: /usr/bin/script.sh %MN% will execute as /usr/bin/script.sh MonitorName /path/to/event. Please note that urls may contain characters like & that need quoting. So you may need to put quotes around them like /usr/bin/scrupt.sh "%MN%".
|
||||
* Delete all matches: Deletes all the matched events.
|
||||
* Email details of all matches: Sends an email to the configured address with details about the event.
|
||||
* Copy all matches: copies the event files to another location, specified in the Copy To dropdown. The other location must be setup in the Storage Tab under options.
|
||||
|
|
|
@ -53,7 +53,7 @@ This screen is called the "console" screen in ZoneMinder and shows a summary of
|
|||
* **B**: This brings up a color coded log window that shows various system and component level logs. This window is useful if you are trying to diagnose issues. Refer to :doc:`logging`.
|
||||
* **C**: ZoneMinder allows you to group monitors for logical separation. This option lets you create new groups, associate monitors to them and edit/delete existing groups.
|
||||
* **D**: Filters are a powerful mechanism to perform actions when certain conditions are met. ZoneMinder comes with some preset filters that keep a tab of disk space and others. Many users create their own filters for more advanced actions like sending emails when certain events occur and more. Refer to :doc:`filterevents`.
|
||||
* **E**: The Cycle option allows you to rotate between live views of each cofigured monitor.
|
||||
* **E**: The Cycle option allows you to rotate between live views of each configured monitor.
|
||||
* **F**: The Montage option shows a collage of your monitors. You can customize them including moving them around.
|
||||
* **G**: Montage Review allows you to simultaneously view past events for different monitors. Note that this is a very resource intensive page and its performance will vary based on your system capabilities.
|
||||
* **H**: Audit Events Report is more of a power user feature. This option looks for recording gaps in events and recording issues in mp4 files.
|
||||
|
|
|
@ -101,6 +101,6 @@ FROM_EMAIL - The emails or messages that will be sent to you informing you of ev
|
|||
|
||||
URL - The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. ``http://host.your.domain/zm/index.php``.
|
||||
|
||||
SSMTP_MAIL - SSMTP is a lightweight and efficient method to send email. The SSMTP application is not installed by default. NEW_MAIL_MODULES must also be enabled. Please visit the ZoneMinder `SSMTP Wiki page <http://www.zoneminder.com/wiki/index.php/How_to_get_ssmtp_working_with_Zoneminder>`__ for setup and configuration help.
|
||||
SSMTP_MAIL - SSMTP is a lightweight and efficient method to send email. The SSMTP application is not installed by default. NEW_MAIL_MODULES must also be enabled. Please visit the ZoneMinder `SSMTP Wiki page <https://wiki.zoneminder.com/How_to_get_ssmtp_working_with_Zoneminder>`__ for setup and configuration help.
|
||||
|
||||
SSMTP_PATH - The path to the SSMTP application. If path is not defined. Zoneminder will try to determine the path via shell command. Example path: /usr/sbin/ssmtp.
|
||||
SSMTP_PATH - The path to the SSMTP application. If path is not defined. Zoneminder will try to determine the path via shell command. Example path: /usr/sbin/ssmtp.
|
||||
|
|
|
@ -30,7 +30,7 @@ This screen allows you to configure various permissions on a per user basis. The
|
|||
.. note:: if you are using zmNinja, users are required to have 'View' access to system because multi-server information is only available as part of this permission
|
||||
|
||||
- Bandwidth
|
||||
- Specifies the maximum bandwith that this user can configure (Low, Medium or High)
|
||||
- Specifies the maximum bandwidth that this user can configure (Low, Medium or High)
|
||||
|
||||
- API enabled
|
||||
- Specifies if the ZoneMinder API is enabled for this user (needs to be on, if you are using a mobile app such as zmNinja)
|
||||
|
@ -42,4 +42,4 @@ Here is an example of a restricted user, for example:
|
|||
|
||||
.. image:: images/Options_Users_Example.png
|
||||
|
||||
This user "home" is enabled, can view live streams and events, but only from "DoorBell" and "DeckCamera". This user also cannot control PTZ.
|
||||
This user "home" is enabled, can view live streams and events, but only from "DoorBell" and "DeckCamera". This user also cannot control PTZ.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
failregex = ^\s*web_php\[\d+\]\.ERR \[<HOST>\].*includes/auth.php
|
||||
datepattern = ^%%m/%%d/%%y %%H:%%M:%%S(?:\.%%f)
|
|
@ -147,7 +147,7 @@ This attribute is of type L<SOAP::WSDL::XSD::Typelib::Builtin::integer|SOAP::WSD
|
|||
|
||||
=item * Cells
|
||||
|
||||
A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
A "1" denotes a cell where motion is detected and a "0" an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2709,7 +2709,7 @@ Returns a L<ONVIF::Device::Elements::GetNetworkInterfacesResponse|ONVIF::Device:
|
|||
|
||||
=head3 SetNetworkInterfaces
|
||||
|
||||
For interoperability with a client unaware of the IEEE 802.11 extension a device shall retain its IEEE 802.11 configuration if the IEEE 802.11 configuration element isn’t present in the request.
|
||||
For interoperability with a client unaware of the IEEE 802.11 extension a device shall retain its IEEE 802.11 configuration if the IEEE 802.11 configuration element isn't present in the request.
|
||||
|
||||
Returns a L<ONVIF::Device::Elements::SetNetworkInterfacesResponse|ONVIF::Device::Elements::SetNetworkInterfacesResponse> object.
|
||||
|
||||
|
@ -3093,7 +3093,7 @@ Returns a L<ONVIF::Device::Elements::SetRelayOutputStateResponse|ONVIF::Device::
|
|||
|
||||
=head3 SendAuxiliaryCommand
|
||||
|
||||
tt:IRLamp|Auto – Request to configure an IR illuminator attached to the unit so that it automatically turns ON and OFF. A device that indicates auxiliary service capability shall support this command.
|
||||
tt:IRLamp|Auto - Request to configure an IR illuminator attached to the unit so that it automatically turns ON and OFF. A device that indicates auxiliary service capability shall support this command.
|
||||
|
||||
Returns a L<ONVIF::Device::Elements::SendAuxiliaryCommandResponse|ONVIF::Device::Elements::SendAuxiliaryCommandResponse> object.
|
||||
|
||||
|
@ -3288,7 +3288,7 @@ Returns a L<ONVIF::Device::Elements::GetSystemUrisResponse|ONVIF::Device::Elemen
|
|||
|
||||
=head3 StartFirmwareUpgrade
|
||||
|
||||
The value of the Content-Type header in the HTTP POST request shall be “application/octetstream”.
|
||||
The value of the Content-Type header in the HTTP POST request shall be "application/octetstream".
|
||||
|
||||
Returns a L<ONVIF::Device::Elements::StartFirmwareUpgradeResponse|ONVIF::Device::Elements::StartFirmwareUpgradeResponse> object.
|
||||
|
||||
|
@ -3298,7 +3298,7 @@ Returns a L<ONVIF::Device::Elements::StartFirmwareUpgradeResponse|ONVIF::Device:
|
|||
|
||||
=head3 StartSystemRestore
|
||||
|
||||
The value of the Content-Type header in the HTTP POST request shall be “application/octetstream”.
|
||||
The value of the Content-Type header in the HTTP POST request shall be "application/octetstream".
|
||||
|
||||
Returns a L<ONVIF::Device::Elements::StartSystemRestoreResponse|ONVIF::Device::Elements::StartSystemRestoreResponse> object.
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ This attribute is of type L<SOAP::WSDL::XSD::Typelib::Builtin::integer|SOAP::WSD
|
|||
|
||||
=item * Cells
|
||||
|
||||
A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
A "1" denotes a cell where motion is detected and a "0" an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2147,7 +2147,7 @@ Returns a L<ONVIF::Media::Elements::GetAudioOutputsResponse|ONVIF::Media::Elemen
|
|||
|
||||
=head3 CreateProfile
|
||||
|
||||
This operation creates a new empty media profile. The media profile shall be created in the device and shall be persistent (remain after reboot). A created profile shall be deletable and a device shall set the “fixed” attribute to false in the returned Profile.
|
||||
This operation creates a new empty media profile. The media profile shall be created in the device and shall be persistent (remain after reboot). A created profile shall be deletable and a device shall set the "fixed" attribute to false in the returned Profile.
|
||||
|
||||
Returns a L<ONVIF::Media::Elements::CreateProfileResponse|ONVIF::Media::Elements::CreateProfileResponse> object.
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ This attribute is of type L<SOAP::WSDL::XSD::Typelib::Builtin::integer|SOAP::WSD
|
|||
|
||||
=item * Cells
|
||||
|
||||
A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
A "1" denotes a cell where motion is detected and a "0" an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -987,7 +987,7 @@ Returns a L<ONVIF::PTZ::Elements::GotoHomePositionResponse|ONVIF::PTZ::Elements:
|
|||
|
||||
=head3 SetHomePosition
|
||||
|
||||
Operation to save current position as the home position. The SetHomePosition command returns with a failure if the “home” position is fixed and cannot be overwritten. If the SetHomePosition is successful, it is possible to recall the Home Position with the GotoHomePosition command.
|
||||
Operation to save current position as the home position. The SetHomePosition command returns with a failure if the "home" position is fixed and cannot be overwritten. If the SetHomePosition is successful, it is possible to recall the Home Position with the GotoHomePosition command.
|
||||
|
||||
Returns a L<ONVIF::PTZ::Elements::SetHomePositionResponse|ONVIF::PTZ::Elements::SetHomePositionResponse> object.
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ This attribute is of type L<SOAP::WSDL::XSD::Typelib::Builtin::integer|SOAP::WSD
|
|||
|
||||
=item * Cells
|
||||
|
||||
A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
A "1" denotes a cell where motion is detected and a "0" an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ of the corresponding class can be passed instead of the marked hash ref.
|
|||
You may pass any combination of objects, hash and list refs to these
|
||||
methods, as long as you meet the structure.
|
||||
|
||||
List items (i.e. multiple occurences) are not displayed in the synopsis.
|
||||
List items (i.e. multiple occurrences) are not displayed in the synopsis.
|
||||
You may generally pass a list ref of hash refs (or objects) instead of a hash
|
||||
ref - this may result in invalid XML if used improperly, though. Note that
|
||||
SOAP::WSDL always expects list references at maximum depth position.
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ not checked yet.
|
|||
|
||||
The current implementation of union resorts to inheriting from the base type,
|
||||
which means (quoted from the XML Schema specs): "If the <list> or <union>
|
||||
alternative is chosen, then the simple ur-type definition·."
|
||||
alternative is chosen, then the simple ur-type definition."
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3766,7 +3766,7 @@ our @options = (
|
|||
SSMTP is a lightweight and efficient method to send email.
|
||||
The SSMTP application is not installed by default.
|
||||
NEW_MAIL_MODULES must also be enabled.
|
||||
Please visit the ZoneMinder [SSMTP Wiki page](http://www.zoneminder.com/wiki/index.php/How_to_get_ssmtp_working_with_Zoneminder)
|
||||
Please visit the ZoneMinder [SSMTP Wiki page](https://wiki.zoneminder.com/How_to_get_ssmtp_working_with_Zoneminder)
|
||||
for setup and configuration help.
|
||||
`,
|
||||
type => $types{boolean},
|
||||
|
|
|
@ -220,14 +220,14 @@ sub moveConUpRight {
|
|||
my $self = shift;
|
||||
Debug('Move Diagonally Up Right');
|
||||
$$self{Monitor}->suspendMotionDetection() if !$self->{Monitor}->{ModectDuringPTZ};
|
||||
$$self{LastCmd} = 'code=RightUp&channel=0&arg1=0&arg2=1&arg3=0';
|
||||
$$self{LastCmd} = 'code=RightUp&channel=0&arg1=1&arg2=1&arg3=0';
|
||||
$self->sendCmd('cgi-bin/ptz.cgi?action=start&'.$$self{LastCmd});
|
||||
}
|
||||
|
||||
sub moveConDownRight {
|
||||
my $self = shift;
|
||||
Debug('Move Diagonally Down Right');
|
||||
$$self{LastCmd} = 'code=RightDown&channel=0&arg1=0&arg2=1&arg3=0';
|
||||
$$self{LastCmd} = 'code=RightDown&channel=0&arg1=1&arg2=1&arg3=0';
|
||||
$$self{Monitor}->suspendMotionDetection() if !$self->{Monitor}->{ModectDuringPTZ};
|
||||
$self->sendCmd('cgi-bin/ptz.cgi?action=start&'.$$self{LastCmd});
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ sub moveConUpLeft {
|
|||
my $self = shift;
|
||||
Debug('Move Diagonally Up Left');
|
||||
$$self{Monitor}->suspendMotionDetection() if !$self->{Monitor}->{ModectDuringPTZ};
|
||||
$$self{LastCmd} = 'code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0';
|
||||
$$self{LastCmd} = 'code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0';
|
||||
$self->sendCmd('cgi-bin/ptz.cgi?action=start&'.$$self{LastCmd});
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ sub moveConDownLeft {
|
|||
my $self = shift;
|
||||
Debug('Move Diagonally Down Left');
|
||||
$$self{Monitor}->suspendMotionDetection() if !$self->{Monitor}->{ModectDuringPTZ};
|
||||
$$self{LastCmd} = 'code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0';
|
||||
$$self{LastCmd} = 'code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0';
|
||||
$self->sendCmd('cgi-bin/ptz.cgi?action=start&'.$$self{LastCmd});
|
||||
}
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ None by default.
|
|||
=head1 SEE ALSO
|
||||
|
||||
See if there are better instructions for the DCS-5020L at
|
||||
http://www.zoneminder.com/wiki/index.php/Dlink
|
||||
https://wiki.zoneminder.com/Dlink
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ sub presetSet
|
|||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=0";
|
||||
my $cmd = 'form/presetSet?flag=3&existFlag=1&language=cn&presetNum='.$preset;
|
||||
$self->sendCmd( $cmd );
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ sub presetGoto
|
|||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=1";
|
||||
my $cmd = 'form/presetSet?flag=4&existFlag=1&language=cn&presetNum='.$preset;
|
||||
$self->sendCmd( $cmd );
|
||||
}
|
||||
|
||||
|
|
|
@ -756,9 +756,9 @@ sub CopyTo {
|
|||
} # end sub CopyTo
|
||||
|
||||
sub MoveTo {
|
||||
my ( $self, $NewStorage ) = @_;
|
||||
my ($self, $NewStorage) = @_;
|
||||
|
||||
if ( !$self->canEdit() ) {
|
||||
if (!$self->canEdit()) {
|
||||
Warning('No permission to move event.');
|
||||
return 'No permission to move event.';
|
||||
}
|
||||
|
@ -772,11 +772,9 @@ sub MoveTo {
|
|||
$$self{StorageId} = $$NewStorage{Id};
|
||||
$self->Storage($NewStorage);
|
||||
$error .= $self->save();
|
||||
if ( $error ) {
|
||||
$ZoneMinder::Database::dbh->commit();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$ZoneMinder::Database::dbh->commit();
|
||||
$self->delete_files($OldStorage);
|
||||
return $error;
|
||||
} # end sub MoveTo
|
||||
|
|
|
@ -127,9 +127,11 @@ sub Execute {
|
|||
foreach my $term ( @{$$self{PostSQLConditions}} ) {
|
||||
if ( $$term{attr} eq 'ExistsInFileSystem' ) {
|
||||
foreach my $row ( @results ) {
|
||||
my $event = new ZoneMinder::Event($row);
|
||||
my $event = new ZoneMinder::Event($$row{Id}, $row);
|
||||
if ( -e $event->Path() ) {
|
||||
push @filtered_events, $row;
|
||||
push @filtered_events, $row if $$term{val} eq 'true';
|
||||
} else {
|
||||
push @filtered_events, $row if $$term{val} eq 'false';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,138 +166,142 @@ sub Sql {
|
|||
if ( exists($term->{obr}) ) {
|
||||
$self->{Sql} .= str_repeat('(', $term->{obr}).' ';
|
||||
}
|
||||
if (!$term->{attr}) {
|
||||
Error("Invalid term in filter $$self{Id}. Empty attr");
|
||||
next;
|
||||
}
|
||||
|
||||
my $value = $term->{val};
|
||||
my @value_list;
|
||||
if ( $term->{attr} ) {
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$term->{op} = 'EXISTS';
|
||||
} elsif ( $term->{attr} =~ /^Monitor/ ) {
|
||||
$sql = 'SELECT E.*, unix_timestamp(E.StartDateTime) as Time, M.Name as MonitorName
|
||||
FROM Events as E INNER JOIN Monitors as M on M.Id = E.MonitorId';
|
||||
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||
$self->{Sql} .= 'M.'.$temp_attr_name;
|
||||
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
||||
$sql = 'SELECT E.*, unix_timestamp(E.StartDateTime) as Time, M.Name as MonitorName
|
||||
FROM Events as E INNER JOIN Monitors as M on M.Id = E.MonitorId';
|
||||
$self->{Sql} .= 'M.ServerId';
|
||||
} elsif ( $term->{attr} eq 'StorageServerId' ) {
|
||||
$self->{Sql} .= '(SELECT Storage.ServerId FROM Storage WHERE Storage.Id=E.StorageId)';
|
||||
} elsif ( $term->{attr} eq 'FilterServerId' ) {
|
||||
$self->{Sql} .= $Config{ZM_SERVER_ID};
|
||||
# StartTime options
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
$self->{Sql} .= 'E.StartDateTime';
|
||||
} elsif ( $term->{attr} eq 'Date' ) {
|
||||
$self->{Sql} .= 'to_days( E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'StartDate' ) {
|
||||
$self->{Sql} .= 'to_days( E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' ) {
|
||||
$self->{Sql} .= 'extract( hour_second from E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'Weekday' or $term->{attr} eq 'StartWeekday' ) {
|
||||
$self->{Sql} .= 'weekday( E.StartDateTime )';
|
||||
|
||||
# EndTIme options
|
||||
} elsif ( $term->{attr} eq 'EndDateTime' ) {
|
||||
$self->{Sql} .= 'E.EndDateTime';
|
||||
} elsif ( $term->{attr} eq 'EndDate' ) {
|
||||
$self->{Sql} .= 'to_days( E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'EndTime' ) {
|
||||
$self->{Sql} .= 'extract( hour_second from E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'EndWeekday' ) {
|
||||
$self->{Sql} .= 'weekday( E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'ExistsInFileSystem' ) {
|
||||
push @{$self->{PostSQLConditions}}, $term;
|
||||
$self->{Sql} .= 'TRUE /* ExistsInFileSystem */';
|
||||
} elsif ( $term->{attr} eq 'DiskPercent' ) {
|
||||
$self->{Sql} .= 'zmDiskPercent';
|
||||
$self->{HasDiskPercent} = !undef;
|
||||
} elsif ( $term->{attr} eq 'DiskBlocks' ) {
|
||||
$self->{Sql} .= 'zmDiskBlocks';
|
||||
$self->{HasDiskBlocks} = !undef;
|
||||
} elsif ( $term->{attr} eq 'SystemLoad' ) {
|
||||
$self->{Sql} .= 'zmSystemLoad';
|
||||
$self->{HasSystemLoad} = !undef;
|
||||
} else {
|
||||
$self->{Sql} .= 'E.'.$term->{attr};
|
||||
}
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$term->{op} = 'EXISTS';
|
||||
} elsif ( $term->{attr} =~ /^Monitor/ ) {
|
||||
$sql = 'SELECT E.*, unix_timestamp(E.StartDateTime) as Time, M.Name as MonitorName
|
||||
FROM Events as E INNER JOIN Monitors as M on M.Id = E.MonitorId';
|
||||
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||
$self->{Sql} .= 'M.'.$temp_attr_name;
|
||||
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
||||
$sql = 'SELECT E.*, unix_timestamp(E.StartDateTime) as Time, M.Name as MonitorName
|
||||
FROM Events as E INNER JOIN Monitors as M on M.Id = E.MonitorId';
|
||||
$self->{Sql} .= 'M.ServerId';
|
||||
} elsif ( $term->{attr} eq 'StorageServerId' ) {
|
||||
$self->{Sql} .= '(SELECT Storage.ServerId FROM Storage WHERE Storage.Id=E.StorageId)';
|
||||
} elsif ( $term->{attr} eq 'FilterServerId' ) {
|
||||
$self->{Sql} .= $Config{ZM_SERVER_ID};
|
||||
# StartTime options
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
$self->{Sql} .= 'E.StartDateTime';
|
||||
} elsif ( $term->{attr} eq 'Date' ) {
|
||||
$self->{Sql} .= 'to_days( E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'StartDate' ) {
|
||||
$self->{Sql} .= 'to_days( E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' ) {
|
||||
$self->{Sql} .= 'extract( hour_second from E.StartDateTime )';
|
||||
} elsif ( $term->{attr} eq 'Weekday' or $term->{attr} eq 'StartWeekday' ) {
|
||||
$self->{Sql} .= 'weekday( E.StartDateTime )';
|
||||
|
||||
if ( $term->{attr} eq 'ExistsInFileSystem' ) {
|
||||
# PostCondition, so no further SQL
|
||||
} else {
|
||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
||||
# EndTIme options
|
||||
} elsif ( $term->{attr} eq 'EndDateTime' ) {
|
||||
$self->{Sql} .= 'E.EndDateTime';
|
||||
} elsif ( $term->{attr} eq 'EndDate' ) {
|
||||
$self->{Sql} .= 'to_days( E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'EndTime' ) {
|
||||
$self->{Sql} .= 'extract( hour_second from E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'EndWeekday' ) {
|
||||
$self->{Sql} .= 'weekday( E.EndDateTime )';
|
||||
} elsif ( $term->{attr} eq 'ExistsInFileSystem' ) {
|
||||
push @{$self->{PostSQLConditions}}, $term;
|
||||
$self->{Sql} .= 'TRUE /* ExistsInFileSystem */';
|
||||
} elsif ( $term->{attr} eq 'DiskPercent' ) {
|
||||
$self->{Sql} .= 'zmDiskPercent';
|
||||
$self->{HasDiskPercent} = !undef;
|
||||
} elsif ( $term->{attr} eq 'DiskBlocks' ) {
|
||||
$self->{Sql} .= 'zmDiskBlocks';
|
||||
$self->{HasDiskBlocks} = !undef;
|
||||
} elsif ( $term->{attr} eq 'SystemLoad' ) {
|
||||
$self->{Sql} .= 'zmSystemLoad';
|
||||
$self->{HasSystemLoad} = !undef;
|
||||
} else {
|
||||
$self->{Sql} .= 'E.'.$term->{attr};
|
||||
}
|
||||
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND Score > 0 AND ZoneId='.$value.')';
|
||||
} elsif ( $term->{attr} =~ /^MonitorName/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} =~ /ServerId/) {
|
||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
||||
if ( $temp_value eq 'ZM_SERVER_ID' ) {
|
||||
$value = "'$ZoneMinder::Config::Config{ZM_SERVER_ID}'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server($ZoneMinder::Config::Config{ZM_SERVER_ID});
|
||||
} elsif ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = "'$temp_value'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server($temp_value);
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'StorageId' ) {
|
||||
$value = "'$temp_value'";
|
||||
$$self{Storage} = new ZoneMinder::Storage($temp_value);
|
||||
} elsif ( $term->{attr} eq 'Name'
|
||||
|| $term->{attr} eq 'Cause'
|
||||
|| $term->{attr} eq 'Notes'
|
||||
) {
|
||||
if ( $term->{op} eq 'LIKE'
|
||||
|| $term->{op} eq 'NOT LIKE'
|
||||
) {
|
||||
$temp_value = '%'.$temp_value.'%' if $temp_value !~ /%/;
|
||||
}
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "'$value'";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} elsif ( $temp_value eq 'CURDATE()' or $temp_value eq 'NOW()' ) {
|
||||
$value = 'to_days('.$temp_value.')';
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "to_days( '$value' )";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "extract( hour_second from '$value' )";
|
||||
}
|
||||
} else {
|
||||
if ( $term->{attr} eq 'ExistsInFileSystem' ) {
|
||||
# PostCondition, so no further SQL
|
||||
} else {
|
||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $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/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} =~ /ServerId/) {
|
||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
||||
if ( $temp_value eq 'ZM_SERVER_ID' ) {
|
||||
$value = "'$ZoneMinder::Config::Config{ZM_SERVER_ID}'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server($ZoneMinder::Config::Config{ZM_SERVER_ID});
|
||||
} elsif ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = "'$temp_value'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server($temp_value);
|
||||
}
|
||||
push @value_list, $value;
|
||||
} # end foreach temp_value
|
||||
} # end if has an attr
|
||||
} elsif ( $term->{attr} eq 'StorageId' ) {
|
||||
$value = "'$temp_value'";
|
||||
$$self{Storage} = new ZoneMinder::Storage($temp_value);
|
||||
} elsif ( $term->{attr} eq 'Name'
|
||||
|| $term->{attr} eq 'Cause'
|
||||
|| $term->{attr} eq 'Notes'
|
||||
) {
|
||||
if ( $term->{op} eq 'LIKE'
|
||||
|| $term->{op} eq 'NOT LIKE'
|
||||
) {
|
||||
$temp_value = '%'.$temp_value.'%' if $temp_value !~ /%/;
|
||||
}
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "'$value'";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} elsif ( $temp_value eq 'CURDATE()' or $temp_value eq 'NOW()' ) {
|
||||
$value = 'to_days('.$temp_value.')';
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "to_days( '$value' )";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
Error("Error parsing date/time '$temp_value', skipping filter '$self->{Name}'");
|
||||
return;
|
||||
}
|
||||
$value = "extract( hour_second from '$value' )";
|
||||
}
|
||||
} else {
|
||||
$value = $temp_value;
|
||||
}
|
||||
push @value_list, $value;
|
||||
} # end foreach temp_value
|
||||
|
||||
if ( $term->{op} ) {
|
||||
if ( $term->{op} eq '=~' ) {
|
||||
|
|
|
@ -136,8 +136,8 @@ $serial = $primary_key = 'Id';
|
|||
%defaults = (
|
||||
ServerId => 0,
|
||||
StorageId => 0,
|
||||
Type => 'Ffmpeg',
|
||||
Function => 'Mocord',
|
||||
Type => q`'Ffmpeg'`,
|
||||
Function => q`'Mocord'`,
|
||||
Enabled => 1,
|
||||
LinkedMonitors => undef,
|
||||
Device => '',
|
||||
|
@ -166,15 +166,15 @@ $serial = $primary_key = 'Id';
|
|||
VideoWriter => 0,
|
||||
OutputCodec => undef,
|
||||
OutputContainer => undef,
|
||||
EncoderParameters => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
|
||||
EncoderParameters => '',
|
||||
RecordAudio=>0,
|
||||
RTSPDescribe=>0,
|
||||
Brightness => -1,
|
||||
Contrast => -1,
|
||||
Hue => -1,
|
||||
Colour => -1,
|
||||
EventPrefix => 'Event-',
|
||||
LabelFormat => '%N - %d/%m/%y %H:%M:%S',
|
||||
EventPrefix => q`'Event-'`,
|
||||
LabelFormat => '',
|
||||
LabelX => 0,
|
||||
LabelY => 0,
|
||||
LabelSize => 1,
|
||||
|
@ -208,13 +208,13 @@ $serial = $primary_key = 'Id';
|
|||
DefaultRate => 100,
|
||||
DefaultScale => 100,
|
||||
SignalCheckPoints => 0,
|
||||
SignalCheckColour => '#0000BE',
|
||||
WebColour => '#ff0000',
|
||||
SignalCheckColour => q`'#0000BE'`,
|
||||
WebColour => q`'#ff0000'`,
|
||||
Exif => 0,
|
||||
Sequence => undef,
|
||||
ZoneCount => 0,
|
||||
Refresh => undef,
|
||||
DefaultCodec => 'auto',
|
||||
DefaultCodec => q`'auto'`,
|
||||
Latitude => undef,
|
||||
Longitude => undef,
|
||||
);
|
||||
|
@ -279,21 +279,37 @@ sub disconnect {
|
|||
sub suspendMotionDetection {
|
||||
my $self = shift;
|
||||
return 0 if ! ZoneMinder::Memory::zmMemVerify($self);
|
||||
while (ZoneMinder::Memory::zmMemRead($self, 'shared_data:active', 1)) {
|
||||
return if $$self{Function} eq 'Nodect' or $$self{Function} eq 'Monitor' or $$self{Function} eq 'None';
|
||||
my $count = 50;
|
||||
while ($count and ZoneMinder::Memory::zmMemRead($self, 'shared_data:active', 1)) {
|
||||
ZoneMinder::Logger::Debug(1, 'Suspending motion detection');
|
||||
ZoneMinder::Memory::zmMonitorSuspend($self);
|
||||
usleep(100000);
|
||||
$count -= 1;
|
||||
}
|
||||
if (!$count) {
|
||||
ZoneMinder::Logger::Error('Unable to suspend motion detection after 5 seconds.');
|
||||
ZoneMinder::Memory::zmMemInvalidate($self); # Close our file handle to the zmc process we are about to end
|
||||
} else {
|
||||
ZoneMinder::Logger::Debug(1, 'shared_data:active='.ZoneMinder::Memory::zmMemRead($self, 'shared_data:active', 1));
|
||||
}
|
||||
ZoneMinder::Logger::Debug(1,ZoneMinder::Memory::zmMemRead($self, 'shared_data:active', 1));
|
||||
}
|
||||
|
||||
sub resumeMotionDetection {
|
||||
my $self = shift;
|
||||
return 0 if ! ZoneMinder::Memory::zmMemVerify($self);
|
||||
#while (zmMemRead($self, 'shared_data:active', 1)) {
|
||||
return if $$self{Function} eq 'Nodect' or $$self{Function} eq 'Monitor' or $$self{Function} eq 'None';
|
||||
my $count = 50;
|
||||
while ($count and !ZoneMinder::Memory::zmMemRead($self, 'shared_data:active', 1)) {
|
||||
ZoneMinder::Logger::Debug(1, 'Resuming motion detection');
|
||||
ZoneMinder::Memory::zmMonitorResume($self);
|
||||
#}
|
||||
ZoneMinder::Memory::zmMonitorResume($self);
|
||||
usleep(100000);
|
||||
$count -= 1;
|
||||
}
|
||||
if (!$count) {
|
||||
ZoneMinder::Logger::Error('Unable to resume motion detection after 5 seconds.');
|
||||
ZoneMinder::Memory::zmMemInvalidate($self); # Close our file handle to the zmc process we are about to end
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,10 @@ $serial = $primary_key = 'Id';
|
|||
MonitorId
|
||||
Type
|
||||
Units
|
||||
NumCoords
|
||||
Coords
|
||||
Area
|
||||
AlarmRGB
|
||||
CheckMethod
|
||||
MinPixelThreshold
|
||||
MaxPixelThreshold
|
||||
|
@ -59,9 +63,13 @@ $serial = $primary_key = 'Id';
|
|||
|
||||
%defaults = (
|
||||
Name => '',
|
||||
Type => 'Active',
|
||||
Units => 'Pixels',
|
||||
CheckMethod => 'Blobs',
|
||||
Type => q`'Active'`,
|
||||
Units => q`'Pixels'`,
|
||||
NumCoords => 0,
|
||||
Coords => '',
|
||||
Area => 0,
|
||||
AlarmRGB => 0,
|
||||
CheckMethod => q`'Blobs'`,
|
||||
MinPixelThreshold => undef,
|
||||
MaxPixelThreshold => undef,
|
||||
MinAlarmPixels => undef,
|
||||
|
|
|
@ -61,12 +61,12 @@ GetOptions(
|
|||
'autostop' =>\$options{autostop},
|
||||
) or pod2usage(-exitstatus => -1);
|
||||
|
||||
if ( !$id ) {
|
||||
if (!$id) {
|
||||
print(STDERR "Please give a valid monitor id\n");
|
||||
pod2usage(-exitstatus => -1);
|
||||
}
|
||||
|
||||
( $id ) = $id =~ /^(\w+)$/;
|
||||
($id) = $id =~ /^(\w+)$/;
|
||||
logInit($id?(id=>'zmcontrol_'.$id):());
|
||||
|
||||
my $sock_file = $Config{ZM_PATH_SOCKS}.'/zmcontrol-'.$id.'.sock';
|
||||
|
@ -76,7 +76,7 @@ socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
|
|||
|
||||
my $saddr = sockaddr_un($sock_file);
|
||||
|
||||
if ( $options{command} ) {
|
||||
if ($options{command}) {
|
||||
# Have a command, so we are the client, connect to the server and send it.
|
||||
|
||||
my $tries = 10;
|
||||
|
@ -101,18 +101,16 @@ if ( $options{command} ) {
|
|||
Error("Unable to connect to zmcontrol server at $sock_file");
|
||||
}
|
||||
} else {
|
||||
|
||||
# The server isn't there
|
||||
my $monitor = zmDbGetMonitorAndControl($id);
|
||||
if ( !$monitor ) {
|
||||
Fatal("Unable to load control data for monitor $id");
|
||||
}
|
||||
Fatal("Unable to load control data for monitor $id") if !$monitor;
|
||||
|
||||
my $protocol = $monitor->{Protocol};
|
||||
if ( !$protocol ) {
|
||||
if (!$protocol) {
|
||||
Fatal('No protocol is set in monitor. Please edit the monitor, edit control type, select the control capability and fill in the Protocol field');
|
||||
}
|
||||
|
||||
if ( -x $protocol ) {
|
||||
if (-x $protocol) {
|
||||
# Protocol is actually a script!
|
||||
# Holdover from previous versions
|
||||
my $command .= $protocol.' '.$arg_string;
|
||||
|
@ -120,11 +118,11 @@ if ( $options{command} ) {
|
|||
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
if ($status || logDebugging()) {
|
||||
chomp($output);
|
||||
Debug("Output: $output");
|
||||
}
|
||||
if ( $status ) {
|
||||
if ($status) {
|
||||
Error("Command '$command' exited with status: $status");
|
||||
exit($status);
|
||||
}
|
||||
|
@ -134,7 +132,7 @@ if ( $options{command} ) {
|
|||
Info("Starting control server $id/$protocol");
|
||||
close(CLIENT);
|
||||
|
||||
if ( ! can_load( modules => { "ZoneMinder::Control::$protocol" => undef } ) ) {
|
||||
if (!can_load(modules => {'ZoneMinder::Control::'.$protocol => undef})) {
|
||||
Fatal("Can't load ZoneMinder::Control::$protocol\n$Module::Load::Conditional::ERROR");
|
||||
}
|
||||
|
||||
|
@ -159,7 +157,7 @@ if ( $options{command} ) {
|
|||
$control->open();
|
||||
|
||||
# If we have a command when starting up, then do it.
|
||||
if ( $options{command} ) {
|
||||
if ($options{command}) {
|
||||
my $command = $options{command};
|
||||
$control->$command(\%options);
|
||||
}
|
||||
|
|
|
@ -358,25 +358,27 @@ sub checkFilter {
|
|||
}
|
||||
} # end if AutoDelete
|
||||
|
||||
if ( $filter->{AutoMove} ) {
|
||||
my $NewStorage = new ZoneMinder::Storage($filter->{AutoMoveTo});
|
||||
Info("Moving event $Event->{Id} to datastore $filter->{AutoMoveTo}");
|
||||
$_ = $Event->MoveTo($NewStorage);
|
||||
Error($_) if $_;
|
||||
if ($filter->{AutoMove}) {
|
||||
my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoMoveTo});
|
||||
if ($NewStorage) {
|
||||
Info("Moving event $Event->{Id} to datastore $filter->{AutoMoveTo}");
|
||||
$_ = $Event->MoveTo($NewStorage);
|
||||
Error($_) if $_;
|
||||
} else {
|
||||
Error("No storage area found for move to operation. AutoMoveTo was $$filter{AutoMoveTo}");
|
||||
}
|
||||
}
|
||||
if ( $filter->{AutoCopy} ) {
|
||||
if ($filter->{AutoCopy}) {
|
||||
# Copy To is different from MoveTo in that it JUST copies the files
|
||||
# So we still need to update the Event object with the new SecondaryStorageId
|
||||
my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoCopyTo});
|
||||
if ( $NewStorage ) {
|
||||
Info("Copying event $Event->{Id} to datastore $filter->{AutoCopyTo}");
|
||||
$_ = $Event->CopyTo($NewStorage);
|
||||
if ( $_ ) {
|
||||
$ZoneMinder::Database::dbh->commit();
|
||||
if ($_) {
|
||||
Error($_);
|
||||
} else {
|
||||
$Event->save({SecondaryStorageId=>$$NewStorage{Id}});
|
||||
$ZoneMinder::Database::dbh->commit();
|
||||
}
|
||||
} else {
|
||||
Error("No storage area found for copy to operation. AutoCopyTo was $$filter{AutoCopyTo}");
|
||||
|
@ -399,7 +401,6 @@ sub checkFilter {
|
|||
) {
|
||||
$Event->save();
|
||||
}
|
||||
$ZoneMinder::Database::dbh->commit() if !$$filter{LockRows};
|
||||
} # end if UpdateDiskSpace
|
||||
} # end foreach event
|
||||
ZoneMinder::Database::end_transaction($dbh, $in_transaction) if $$filter{LockRows};
|
||||
|
@ -843,7 +844,7 @@ sub sendEmail {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Info('Creating notification email');
|
||||
Debug('Creating notification email');
|
||||
|
||||
my $subject = substituteTags($$filter{EmailSubject}, $filter, $Event);
|
||||
return 0 if !$subject;
|
||||
|
@ -851,7 +852,7 @@ sub sendEmail {
|
|||
my $body = substituteTags($$filter{EmailBody}, $filter, $Event, \@attachments);
|
||||
return 0 if !$body;
|
||||
|
||||
Info("Sending notification email '$subject'");
|
||||
Debug("Sending notification email '$subject'");
|
||||
|
||||
eval {
|
||||
if ( $Config{ZM_NEW_MAIL_MODULES} ) {
|
||||
|
@ -864,7 +865,7 @@ sub sendEmail {
|
|||
);
|
||||
### Add the text message part
|
||||
$mail->attach (
|
||||
Type => 'TEXT',
|
||||
Type => (($body=~/<html/)?'text/html':'text/plain'),
|
||||
Data => $body
|
||||
);
|
||||
### Add the attachments
|
||||
|
@ -886,9 +887,7 @@ sub sendEmail {
|
|||
if ( $Config{ZM_SSMTP_MAIL} ) {
|
||||
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
||||
if ( !$ssmtp_location ) {
|
||||
if ( logDebugging() ) {
|
||||
Debug("which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message");
|
||||
}
|
||||
Debug("which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message");
|
||||
$ssmtp_location = qx('which ssmtp');
|
||||
}
|
||||
if ( !$ssmtp_location ) {
|
||||
|
@ -916,7 +915,7 @@ sub sendEmail {
|
|||
foreach my $attachment ( @attachments ) {
|
||||
my $size = -s $attachment->{path};
|
||||
$total_size += $size;
|
||||
Info("Attaching '$attachment->{path}' which is $size bytes");
|
||||
Debug("Attaching '$attachment->{path}' which is $size bytes");
|
||||
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
|
@ -934,7 +933,7 @@ sub sendEmail {
|
|||
Error("Unable to send email: $@");
|
||||
return 0;
|
||||
} else {
|
||||
Info('Notification email sent');
|
||||
Info("Notification email sent to $$filter{EmailTo}");
|
||||
}
|
||||
my $sql = 'UPDATE `Events` SET `Emailed` = 1 WHERE `Id` = ?';
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
|
|
|
@ -27,7 +27,7 @@ zmupdate.pl - check and upgrade ZoneMinder database
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
zmupdate.pl -c,--check | -f,--freshen | -v<version>,--version=<version> [-u<dbuser> -p<dbpass>]
|
||||
zmupdate.pl -c,--check | -f,--freshen | -v<version>,--version=<version> [-u <dbuser> -p <dbpass>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
|
|
@ -98,19 +98,19 @@ while (!$zm_terminate) {
|
|||
next if $monitor->{Type} eq 'WebSite';
|
||||
my $now = time();
|
||||
my $restart = 0;
|
||||
if ( zmMemVerify($monitor) ) {
|
||||
if (zmMemVerify($monitor)) {
|
||||
# Check we have got an image recently
|
||||
my $capture_time = zmGetLastWriteTime($monitor);
|
||||
if ( !defined($capture_time) ) {
|
||||
if (!defined($capture_time)) {
|
||||
# Can't read from shared data
|
||||
Debug('LastWriteTime is not defined.');
|
||||
zmMemInvalidate($monitor);
|
||||
next;
|
||||
}
|
||||
Debug("Monitor $$monitor{Id} LastWriteTime is $capture_time.");
|
||||
if ( !$capture_time ) {
|
||||
if (!$capture_time) {
|
||||
my $startup_time = zmGetStartupTime($monitor);
|
||||
if ( ( $now - $startup_time ) > $Config{ZM_WATCH_MAX_DELAY} ) {
|
||||
if (($now - $startup_time) > $Config{ZM_WATCH_MAX_DELAY}) {
|
||||
Warning(
|
||||
"Restarting capture daemon for $$monitor{Name}, no image since startup. ".
|
||||
"Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}"
|
||||
|
@ -122,7 +122,7 @@ while (!$zm_terminate) {
|
|||
next;
|
||||
}
|
||||
}
|
||||
if ( ! $restart ) {
|
||||
if (!$restart) {
|
||||
my $max_image_delay = (
|
||||
$monitor->{MaxFPS}
|
||||
&&($monitor->{MaxFPS}>0)
|
||||
|
@ -144,29 +144,28 @@ while (!$zm_terminate) {
|
|||
$restart = 1;
|
||||
}
|
||||
|
||||
if ( $restart ) {
|
||||
if ($restart) {
|
||||
my $command;
|
||||
if ( $monitor->{Type} eq 'Local' ) {
|
||||
$command = "zmdc.pl restart zmc -d $monitor->{Device}";
|
||||
if ($monitor->{Type} eq 'Local') {
|
||||
$command = 'zmdc.pl restart zmc -d '.$monitor->{Device};
|
||||
} else {
|
||||
$command = "zmdc.pl restart zmc -m $monitor->{Id}";
|
||||
$command = 'zmdc.pl restart zmc -m '.$monitor->{Id};
|
||||
}
|
||||
runCommand($command);
|
||||
} elsif ( $monitor->{Function} ne 'Monitor' ) {
|
||||
} elsif ($monitor->{Function} ne 'Monitor') {
|
||||
# Now check analysis daemon
|
||||
$restart = 0;
|
||||
# Check we have got an image recently
|
||||
my $image_time = zmGetLastReadTime($monitor);
|
||||
if ( !defined($image_time) ) {
|
||||
if (!defined($image_time)) {
|
||||
# Can't read from shared data
|
||||
$restart = 1;
|
||||
Error("Error reading shared data for $$monitor{Id} $$monitor{Name}");
|
||||
} elsif ( !$image_time ) {
|
||||
} elsif (!$image_time) {
|
||||
# We can't get the last capture time so can't be sure it's died.
|
||||
#$restart = 1;
|
||||
Error("Last analyse time for $$monitor{Id} $$monitor{Name} was zero.");
|
||||
} else {
|
||||
|
||||
my $max_image_delay = ( $monitor->{MaxFPS}
|
||||
&&($monitor->{MaxFPS}>0)
|
||||
&&($monitor->{MaxFPS}<1)
|
||||
|
@ -175,7 +174,7 @@ while (!$zm_terminate) {
|
|||
;
|
||||
my $image_delay = $now-$image_time;
|
||||
Debug("Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay");
|
||||
if ( $image_delay > $max_image_delay ) {
|
||||
if ($image_delay > $max_image_delay) {
|
||||
Warning("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
|
||||
." time since last analysis $image_delay seconds ($now-$image_time)"
|
||||
);
|
||||
|
@ -183,13 +182,13 @@ while (!$zm_terminate) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $restart ) {
|
||||
Info("Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n");
|
||||
if ($restart) {
|
||||
Info("Restarting analysis daemon for $$monitor{Id} $$monitor{Name}");
|
||||
my $command;
|
||||
if ( $monitor->{Type} eq 'Local' ) {
|
||||
$command = "zmdc.pl restart zmc -d $monitor->{Device}";
|
||||
$command = 'zmdc.pl restart zmc -d '.$monitor->{Device};
|
||||
} else {
|
||||
$command = "zmdc.pl restart zmc -m $monitor->{Id}";
|
||||
$command = 'zmdc.pl restart zmc -m '.$monitor->{Id};
|
||||
}
|
||||
runCommand($command);
|
||||
} # end if restart
|
||||
|
@ -201,7 +200,7 @@ while (!$zm_terminate) {
|
|||
sleep($Config{ZM_WATCH_CHECK_INTERVAL});
|
||||
} # end while (!$zm_terminate)
|
||||
|
||||
Info("Watchdog exiting");
|
||||
Info('Watchdog exiting');
|
||||
exit();
|
||||
|
||||
1;
|
||||
|
|
|
@ -321,6 +321,7 @@ bool Image::Assign(const AVFrame *frame, SwsContext *convert_context, AVFrame *t
|
|||
return false;
|
||||
}
|
||||
zm_dump_video_frame(temp_frame, "dest frame after convert");
|
||||
update_function_pointers();
|
||||
return true;
|
||||
} // end Image::Assign(const AVFrame *frame, SwsContext *convert_context, AVFrame *temp_frame)
|
||||
|
||||
|
@ -695,6 +696,7 @@ void Image::AssignDirect(
|
|||
subpixelorder = p_subpixelorder;
|
||||
pixels = width * height;
|
||||
size = new_buffer_size;
|
||||
update_function_pointers();
|
||||
} // end void Image::AssignDirect
|
||||
|
||||
void Image::Assign(
|
||||
|
@ -796,6 +798,7 @@ void Image::Assign(const Image &image) {
|
|||
linesize = image.linesize;
|
||||
}
|
||||
|
||||
update_function_pointers();
|
||||
if ( image.buffer != buffer )
|
||||
(*fptr_imgbufcpy)(buffer, image.buffer, size);
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ class Image {
|
|||
|
||||
/* Internal buffer should not be modified from functions outside of this class */
|
||||
inline const uint8_t* Buffer() const { return buffer; }
|
||||
inline const uint8_t* Buffer(unsigned int x, unsigned int y=0) const { return &buffer[(y*linesize)+x]; }
|
||||
inline const uint8_t* Buffer(unsigned int x, unsigned int y=0) const { return &buffer[(y*linesize) + x*colours]; }
|
||||
/* Request writeable buffer */
|
||||
uint8_t* WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
|
||||
// Is only acceptable on a pre-allocated buffer
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if ZM_HAS_V4L
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ std::string load_monitor_sql =
|
|||
"`SectionLength`, `MinSectionLength`, `FrameSkip`, `MotionFrameSkip`, "
|
||||
"`FPSReportInterval`, `RefBlendPerc`, `AlarmRefBlendPerc`, `TrackMotion`, `Exif`,"
|
||||
"`RTSPServer`, `RTSPStreamName`,"
|
||||
"`SignalCheckPoints`, `SignalCheckColour`, `Importance`-2 FROM `Monitors`";
|
||||
"`SignalCheckPoints`, `SignalCheckColour`, `Importance`-1 FROM `Monitors`";
|
||||
|
||||
std::string CameraType_Strings[] = {
|
||||
"Local",
|
||||
|
@ -151,12 +151,12 @@ bool Monitor::MonitorLink::connect() {
|
|||
Debug(1, "link.mem.size=%jd", mem_size);
|
||||
#if ZM_MEM_MAPPED
|
||||
map_fd = open(mem_file.c_str(), O_RDWR, (mode_t)0600);
|
||||
if ( map_fd < 0 ) {
|
||||
if (map_fd < 0) {
|
||||
Debug(3, "Can't open linked memory map file %s: %s", mem_file.c_str(), strerror(errno));
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
while ( map_fd <= 2 ) {
|
||||
while (map_fd <= 2) {
|
||||
int new_map_fd = dup(map_fd);
|
||||
Warning("Got one of the stdio fds for our mmap handle. map_fd was %d, new one is %d", map_fd, new_map_fd);
|
||||
close(map_fd);
|
||||
|
@ -164,31 +164,31 @@ bool Monitor::MonitorLink::connect() {
|
|||
}
|
||||
|
||||
struct stat map_stat;
|
||||
if ( fstat(map_fd, &map_stat) < 0 ) {
|
||||
if (fstat(map_fd, &map_stat) < 0) {
|
||||
Error("Can't stat linked memory map file %s: %s", mem_file.c_str(), strerror(errno));
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( map_stat.st_size == 0 ) {
|
||||
if (map_stat.st_size == 0) {
|
||||
Error("Linked memory map file %s is empty: %s", mem_file.c_str(), strerror(errno));
|
||||
disconnect();
|
||||
return false;
|
||||
} else if ( map_stat.st_size < mem_size ) {
|
||||
} else if (map_stat.st_size < mem_size) {
|
||||
Error("Got unexpected memory map file size %ld, expected %jd", map_stat.st_size, mem_size);
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
mem_ptr = (unsigned char *)mmap(nullptr, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0);
|
||||
if ( mem_ptr == MAP_FAILED ) {
|
||||
if (mem_ptr == MAP_FAILED) {
|
||||
Error("Can't map file %s (%jd bytes) to memory: %s", mem_file.c_str(), mem_size, strerror(errno));
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
#else // ZM_MEM_MAPPED
|
||||
shm_id = shmget((config.shm_key&0xffff0000)|id, mem_size, 0700);
|
||||
if ( shm_id < 0 ) {
|
||||
if (shm_id < 0) {
|
||||
Debug(3, "Can't shmget link memory: %s", strerror(errno));
|
||||
connected = false;
|
||||
return false;
|
||||
|
@ -444,7 +444,7 @@ Monitor::Monitor()
|
|||
"SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, "
|
||||
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif,"
|
||||
"`RTSPServer`,`RTSPStreamName`,
|
||||
"SignalCheckPoints, SignalCheckColour, Importance-2 FROM Monitors";
|
||||
"SignalCheckPoints, SignalCheckColour, Importance-1 FROM Monitors";
|
||||
*/
|
||||
|
||||
void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
||||
|
@ -481,8 +481,18 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
Debug(1, "Have camera type %s", CameraType_Strings[type].c_str());
|
||||
col++;
|
||||
function = (Function)atoi(dbrow[col]); col++;
|
||||
enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
decoding_enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
enabled = dbrow[col] ? atoi(dbrow[col]) : false; col++;
|
||||
decoding_enabled = dbrow[col] ? atoi(dbrow[col]) : false; col++;
|
||||
decoding_enabled = !(
|
||||
( function == RECORD or function == NODECT )
|
||||
and
|
||||
( savejpegs == 0 )
|
||||
and
|
||||
( videowriter == PASSTHROUGH )
|
||||
and
|
||||
!decoding_enabled
|
||||
);
|
||||
Debug(1, "Decoding enabled: %d", decoding_enabled);
|
||||
|
||||
ReloadLinkedMonitors(dbrow[col]); col++;
|
||||
|
||||
|
@ -594,7 +604,7 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
rtsp_server = (*dbrow[col] != '0'); col++;
|
||||
rtsp_streamname = dbrow[col]; col++;
|
||||
|
||||
/*"SignalCheckPoints, SignalCheckColour, Importance-2 FROM Monitors"; */
|
||||
/*"SignalCheckPoints, SignalCheckColour, Importance-1 FROM Monitors"; */
|
||||
signal_check_points = atoi(dbrow[col]); col++;
|
||||
signal_check_colour = strtol(dbrow[col][0] == '#' ? dbrow[col]+1 : dbrow[col], 0, 16); col++;
|
||||
|
||||
|
@ -606,6 +616,7 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
grayscale_val = signal_check_colour & 0xff; /* Clear all bytes but lowest byte */
|
||||
|
||||
importance = dbrow[col] ? atoi(dbrow[col]) : 0;// col++;
|
||||
if (importance < 0) importance = 0; // Should only be >= 0
|
||||
|
||||
// How many frames we need to have before we start analysing
|
||||
ready_count = std::max(warmup_count, pre_event_count);
|
||||
|
@ -653,18 +664,6 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
Error("Can't mkdir %s: %s", monitor_dir.c_str(), strerror(errno));
|
||||
}
|
||||
|
||||
// Do this here to save a few cycles with all the comparisons
|
||||
decoding_enabled = !(
|
||||
( function == RECORD or function == NODECT )
|
||||
and
|
||||
( savejpegs == 0 )
|
||||
and
|
||||
( videowriter == PASSTHROUGH )
|
||||
and
|
||||
!decoding_enabled
|
||||
);
|
||||
Debug(1, "Decoding enabled: %d", decoding_enabled);
|
||||
|
||||
if ( config.record_diag_images ) {
|
||||
if ( config.record_diag_images_fifo ) {
|
||||
diag_path_ref = stringtf("%s/diagpipe-r-%d.jpg", staticConfig.PATH_SOCKS.c_str(), id);
|
||||
|
@ -1061,7 +1060,13 @@ bool Monitor::disconnect() {
|
|||
return true;
|
||||
}
|
||||
|
||||
shared_data->valid = false;
|
||||
if (purpose == CAPTURE) {
|
||||
if (unlink(mem_file.c_str()) < 0) {
|
||||
Warning("Can't unlink '%s': %s", mem_file.c_str(), strerror(errno));
|
||||
}
|
||||
Debug(1, "Setting shared_data->valid = false");
|
||||
shared_data->valid = false;
|
||||
}
|
||||
#if ZM_MEM_MAPPED
|
||||
msync(mem_ptr, mem_size, MS_ASYNC);
|
||||
munmap(mem_ptr, mem_size);
|
||||
|
@ -1071,9 +1076,6 @@ bool Monitor::disconnect() {
|
|||
mem_ptr = nullptr;
|
||||
shared_data = nullptr;
|
||||
|
||||
if (purpose == CAPTURE and (unlink(mem_file.c_str()) < 0) ) {
|
||||
Warning("Can't unlink '%s': %s", mem_file.c_str(), strerror(errno));
|
||||
}
|
||||
#else // ZM_MEM_MAPPED
|
||||
struct shmid_ds shm_data;
|
||||
if (shmctl(shm_id, IPC_STAT, &shm_data) < 0) {
|
||||
|
@ -1094,7 +1096,7 @@ bool Monitor::disconnect() {
|
|||
}
|
||||
#endif // ZM_MEM_MAPPED
|
||||
|
||||
for ( int32_t i = 0; i < image_buffer_count; i++ ) {
|
||||
for (int32_t i = 0; i < image_buffer_count; i++) {
|
||||
// We delete the image because it is an object pointing to space that won't be free'd.
|
||||
delete image_buffer[i];
|
||||
image_buffer[i] = nullptr;
|
||||
|
@ -1108,10 +1110,6 @@ Monitor::~Monitor() {
|
|||
|
||||
if (mem_ptr != nullptr) {
|
||||
if (purpose != QUERY) {
|
||||
shared_data->state = state = IDLE;
|
||||
shared_data->last_read_index = image_buffer_count;
|
||||
shared_data->last_read_time = 0;
|
||||
shared_data->valid = false;
|
||||
memset(mem_ptr, 0, mem_size);
|
||||
} // end if purpose != query
|
||||
disconnect();
|
||||
|
@ -1744,10 +1742,6 @@ bool Monitor::Analyse() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Store the it that points to our snap we will need it later
|
||||
packetqueue_iterator snap_it = *analysis_it;
|
||||
packetqueue.increment_it(analysis_it);
|
||||
|
||||
// signal is set by capture
|
||||
bool signal = shared_data->signal;
|
||||
bool signal_change = (signal != last_signal);
|
||||
|
@ -1857,7 +1851,14 @@ bool Monitor::Analyse() {
|
|||
while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
|
||||
// Need to wait for the decoder thread.
|
||||
Debug(1, "Waiting for decode");
|
||||
packet_lock->wait();
|
||||
packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all
|
||||
packetqueue.wait();
|
||||
|
||||
// Another thread may have moved our it. Unlikely but possible
|
||||
packet_lock = packetqueue.get_packet(analysis_it);
|
||||
if (!packet_lock) return false;
|
||||
snap = packet_lock->packet_;
|
||||
|
||||
if (!snap->image and snap->decoded) {
|
||||
Debug(1, "No image but was decoded, giving up");
|
||||
delete packet_lock;
|
||||
|
@ -1960,14 +1961,14 @@ bool Monitor::Analyse() {
|
|||
// Must start on a keyframe so rewind. Only for passthrough though I guess.
|
||||
// FIXME this iterator is not protected from invalidation
|
||||
packetqueue_iterator *start_it = packetqueue.get_event_start_packet_it(
|
||||
snap_it, 0 /* pre_event_count */
|
||||
*analysis_it, 0 /* pre_event_count */
|
||||
);
|
||||
|
||||
// This gets a lock on the starting packet
|
||||
|
||||
ZMLockedPacket *starting_packet_lock = nullptr;
|
||||
std::shared_ptr<ZMPacket> starting_packet = nullptr;
|
||||
if (*start_it != snap_it) {
|
||||
if (*start_it != *analysis_it) {
|
||||
starting_packet_lock = packetqueue.get_packet(start_it);
|
||||
if (!starting_packet_lock) {
|
||||
Warning("Unable to get starting packet lock");
|
||||
|
@ -1981,12 +1982,12 @@ bool Monitor::Analyse() {
|
|||
|
||||
event = new Event(this, starting_packet->timestamp, "Continuous", noteSetMap);
|
||||
// Write out starting packets, do not modify packetqueue it will garbage collect itself
|
||||
while (starting_packet and ((*start_it) != snap_it)) {
|
||||
while (starting_packet and ((*start_it) != *analysis_it)) {
|
||||
event->AddPacket(starting_packet);
|
||||
// Have added the packet, don't want to unlock it until we have locked the next
|
||||
|
||||
packetqueue.increment_it(start_it);
|
||||
if ((*start_it) == snap_it) {
|
||||
if ((*start_it) == *analysis_it) {
|
||||
if (starting_packet_lock) delete starting_packet_lock;
|
||||
break;
|
||||
}
|
||||
|
@ -2025,8 +2026,7 @@ bool Monitor::Analyse() {
|
|||
} // end if ! event
|
||||
} // end if RECORDING
|
||||
|
||||
if (score) {
|
||||
|
||||
if (score and (function != MONITOR)) {
|
||||
if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) {
|
||||
// If we should end then previous continuous event and start a new non-continuous event
|
||||
if (event && event->Frames()
|
||||
|
@ -2064,12 +2064,12 @@ bool Monitor::Analyse() {
|
|||
|
||||
if (!event) {
|
||||
packetqueue_iterator *start_it = packetqueue.get_event_start_packet_it(
|
||||
snap_it,
|
||||
*analysis_it,
|
||||
(pre_event_count > alarm_frame_count ? pre_event_count : alarm_frame_count)
|
||||
);
|
||||
ZMLockedPacket *starting_packet_lock = nullptr;
|
||||
std::shared_ptr<ZMPacket> starting_packet = nullptr;
|
||||
if (*start_it != snap_it) {
|
||||
if (*start_it != *analysis_it) {
|
||||
starting_packet_lock = packetqueue.get_packet(start_it);
|
||||
if (!starting_packet_lock) return false;
|
||||
starting_packet = starting_packet_lock->packet_;
|
||||
|
@ -2084,11 +2084,11 @@ bool Monitor::Analyse() {
|
|||
shared_data->state = state = ALARM;
|
||||
|
||||
// Write out starting packets, do not modify packetqueue it will garbage collect itself
|
||||
while (*start_it != snap_it) {
|
||||
while (*start_it != *analysis_it) {
|
||||
event->AddPacket(starting_packet);
|
||||
|
||||
packetqueue.increment_it(start_it);
|
||||
if ( (*start_it) == snap_it ) {
|
||||
if ( (*start_it) == (*analysis_it) ) {
|
||||
if (starting_packet_lock) delete starting_packet_lock;
|
||||
break;
|
||||
}
|
||||
|
@ -2279,6 +2279,7 @@ bool Monitor::Analyse() {
|
|||
if (function == MODECT or function == MOCORD)
|
||||
UpdateAnalysisFPS();
|
||||
}
|
||||
packetqueue.increment_it(analysis_it);
|
||||
packetqueue.unlock(packet_lock);
|
||||
shared_data->last_read_time = time(nullptr);
|
||||
|
||||
|
@ -3057,7 +3058,7 @@ int Monitor::PrimeCapture() {
|
|||
Debug(1, "Creating decoder thread");
|
||||
decoder = ZM::make_unique<DecoderThread>(this);
|
||||
} else {
|
||||
Debug(1, "Restartg decoder thread");
|
||||
Debug(1, "Restarting decoder thread");
|
||||
decoder->Start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
break;
|
||||
case CMD_PLAY :
|
||||
Debug(1, "Got PLAY command");
|
||||
if ( paused ) {
|
||||
if (paused) {
|
||||
paused = false;
|
||||
delayed = true;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
break;
|
||||
case CMD_VARPLAY :
|
||||
Debug(1, "Got VARPLAY command");
|
||||
if ( paused ) {
|
||||
if (paused) {
|
||||
paused = false;
|
||||
delayed = true;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
break;
|
||||
case CMD_FASTFWD :
|
||||
Debug(1, "Got FAST FWD command");
|
||||
if ( paused ) {
|
||||
if (paused) {
|
||||
paused = false;
|
||||
delayed = true;
|
||||
}
|
||||
|
@ -135,27 +135,27 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
}
|
||||
break;
|
||||
case CMD_SLOWFWD :
|
||||
Debug( 1, "Got SLOW FWD command" );
|
||||
Debug(1, "Got SLOW FWD command");
|
||||
paused = true;
|
||||
delayed = true;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
step = 1;
|
||||
break;
|
||||
case CMD_SLOWREV :
|
||||
Debug( 1, "Got SLOW REV command" );
|
||||
Debug(1, "Got SLOW REV command");
|
||||
paused = true;
|
||||
delayed = true;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
step = -1;
|
||||
break;
|
||||
case CMD_FASTREV :
|
||||
Debug( 1, "Got FAST REV command" );
|
||||
if ( paused ) {
|
||||
Debug(1, "Got FAST REV command");
|
||||
if (paused) {
|
||||
paused = false;
|
||||
delayed = true;
|
||||
}
|
||||
// Set play rate
|
||||
switch ( replay_rate ) {
|
||||
switch (replay_rate) {
|
||||
case -2 * ZM_RATE_BASE :
|
||||
replay_rate = -5 * ZM_RATE_BASE;
|
||||
break;
|
||||
|
@ -255,7 +255,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
} status_data;
|
||||
|
||||
status_data.id = monitor->Id();
|
||||
if ( ! monitor->ShmValid() ) {
|
||||
if (!monitor->ShmValid()) {
|
||||
status_data.fps = 0.0;
|
||||
status_data.capture_fps = 0.0;
|
||||
status_data.analysis_fps = 0.0;
|
||||
|
@ -265,7 +265,14 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
status_data.forced = false;
|
||||
status_data.buffer_level = 0;
|
||||
} else {
|
||||
status_data.fps = monitor->GetFPS();
|
||||
int elapsed = now.tv_sec - last_fps_update.tv_sec;
|
||||
if (elapsed) {
|
||||
actual_fps = (frame_count - last_frame_count) / elapsed;
|
||||
last_frame_count = frame_count;
|
||||
last_fps_update = now;
|
||||
}
|
||||
|
||||
status_data.fps = actual_fps;
|
||||
status_data.capture_fps = monitor->get_capture_fps();
|
||||
status_data.analysis_fps = monitor->get_analysis_fps();
|
||||
status_data.state = monitor->shared_data->state;
|
||||
|
@ -520,7 +527,7 @@ void MonitorStream::runStream() {
|
|||
Image *paused_image = nullptr;
|
||||
struct timeval paused_timestamp;
|
||||
|
||||
if ( connkey && ( playback_buffer > 0 ) ) {
|
||||
if (connkey && (playback_buffer > 0)) {
|
||||
// 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
|
||||
const int max_swap_len_suffix = 15;
|
||||
|
||||
|
@ -529,27 +536,27 @@ void MonitorStream::runStream() {
|
|||
int subfolder2_length = snprintf(nullptr, 0, "/zmswap-q%06d", connkey) + 1;
|
||||
int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
|
||||
|
||||
if ( total_swap_path_length + max_swap_len_suffix > PATH_MAX ) {
|
||||
if (total_swap_path_length + max_swap_len_suffix > PATH_MAX) {
|
||||
Error("Swap Path is too long. %d > %d ", total_swap_path_length+max_swap_len_suffix, PATH_MAX);
|
||||
} else {
|
||||
swap_path = staticConfig.PATH_SWAP;
|
||||
|
||||
Debug(3, "Checking swap path folder: %s", swap_path.c_str());
|
||||
if ( checkSwapPath(swap_path.c_str(), true) ) {
|
||||
if (checkSwapPath(swap_path.c_str(), true)) {
|
||||
swap_path += stringtf("/zmswap-m%d", monitor->Id());
|
||||
|
||||
Debug(4, "Checking swap path subfolder: %s", swap_path.c_str());
|
||||
if ( checkSwapPath(swap_path.c_str(), true) ) {
|
||||
if (checkSwapPath(swap_path.c_str(), true)) {
|
||||
swap_path += stringtf("/zmswap-q%06d", connkey);
|
||||
|
||||
Debug(4, "Checking swap path subfolder: %s", swap_path.c_str());
|
||||
if ( checkSwapPath(swap_path.c_str(), true) ) {
|
||||
if (checkSwapPath(swap_path.c_str(), true)) {
|
||||
buffered_playback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !buffered_playback ) {
|
||||
if (!buffered_playback) {
|
||||
Error("Unable to validate swap image path, disabling buffered playback");
|
||||
} else {
|
||||
Debug(2, "Assigning temporary buffer");
|
||||
|
@ -560,14 +567,13 @@ void MonitorStream::runStream() {
|
|||
}
|
||||
} else {
|
||||
Debug(2, "Not using playback_buffer");
|
||||
} // end if connkey & playback_buffer
|
||||
} // end if connkey && playback_buffer
|
||||
|
||||
while (!zm_terminate) {
|
||||
bool got_command = false;
|
||||
if ( feof(stdout) ) {
|
||||
if (feof(stdout)) {
|
||||
Debug(2, "feof stdout");
|
||||
break;
|
||||
} else if ( ferror(stdout) ) {
|
||||
} else if (ferror(stdout)) {
|
||||
Debug(2, "ferror stdout");
|
||||
break;
|
||||
} else if (!monitor->ShmValid()) {
|
||||
|
@ -578,8 +584,9 @@ void MonitorStream::runStream() {
|
|||
gettimeofday(&now, nullptr);
|
||||
|
||||
bool was_paused = paused;
|
||||
if ( connkey ) {
|
||||
while ( checkCommandQueue() && !zm_terminate ) {
|
||||
bool got_command = false; // commands like zoom should output a frame even if paused
|
||||
if (connkey) {
|
||||
while (checkCommandQueue() && !zm_terminate) {
|
||||
// Loop in here until all commands are processed.
|
||||
Debug(2, "Have checking command Queue for connkey: %d", connkey);
|
||||
got_command = true;
|
||||
|
@ -591,35 +598,31 @@ void MonitorStream::runStream() {
|
|||
}
|
||||
} // end if connkey
|
||||
|
||||
if ( paused ) {
|
||||
if ( !was_paused ) {
|
||||
if (paused) {
|
||||
if (!was_paused) {
|
||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
||||
Debug(1, "Saving paused image from index %d",index);
|
||||
paused_image = new Image(*monitor->image_buffer[index]);
|
||||
paused_timestamp = monitor->shared_timestamps[index];
|
||||
}
|
||||
} else if ( paused_image ) {
|
||||
Debug(1, "Clearing paused_image");
|
||||
} else if (paused_image) {
|
||||
delete paused_image;
|
||||
paused_image = nullptr;
|
||||
}
|
||||
|
||||
if ( buffered_playback && delayed ) {
|
||||
if ( temp_read_index == temp_write_index ) {
|
||||
if (buffered_playback && delayed) {
|
||||
if (temp_read_index == temp_write_index) {
|
||||
// Go back to live viewing
|
||||
Debug(1, "Exceeded temporary streaming buffer");
|
||||
// Clear paused flag
|
||||
paused = false;
|
||||
// Clear delayed_play flag
|
||||
delayed = false;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
} else {
|
||||
if ( !paused ) {
|
||||
if (!paused) {
|
||||
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
|
||||
// Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index );
|
||||
SwapImage *swap_image = &temp_image_buffer[temp_index];
|
||||
|
||||
if ( !swap_image->valid ) {
|
||||
if (!swap_image->valid) {
|
||||
paused = true;
|
||||
delayed = true;
|
||||
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count);
|
||||
|
@ -632,13 +635,14 @@ void MonitorStream::runStream() {
|
|||
// If the next frame is due
|
||||
if ( actual_delta_time > expected_delta_time ) {
|
||||
// Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
|
||||
if ( temp_index%frame_mod == 0 ) {
|
||||
if ((temp_index % frame_mod) == 0) {
|
||||
Debug(2, "Sending delayed frame %d", temp_index);
|
||||
// Send the next frame
|
||||
if (!sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp)) {
|
||||
zm_terminate = true;
|
||||
}
|
||||
memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp));
|
||||
frame_count++;
|
||||
last_frame_timestamp = swap_image->timestamp;
|
||||
// frame_sent = true;
|
||||
}
|
||||
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count);
|
||||
|
@ -650,17 +654,15 @@ void MonitorStream::runStream() {
|
|||
SwapImage *swap_image = &temp_image_buffer[temp_read_index];
|
||||
|
||||
// Send the next frame
|
||||
if ( !sendFrame(
|
||||
if (!sendFrame(
|
||||
temp_image_buffer[temp_read_index].file_name,
|
||||
temp_image_buffer[temp_read_index].timestamp
|
||||
) ) {
|
||||
temp_image_buffer[temp_read_index].timestamp)
|
||||
) {
|
||||
zm_terminate = true;
|
||||
}
|
||||
memcpy(
|
||||
&last_frame_timestamp,
|
||||
&(swap_image->timestamp),
|
||||
sizeof(last_frame_timestamp)
|
||||
);
|
||||
frame_count++;
|
||||
|
||||
last_frame_timestamp = swap_image->timestamp;
|
||||
// frame_sent = true;
|
||||
step = 0;
|
||||
} else {
|
||||
|
@ -675,12 +677,13 @@ void MonitorStream::runStream() {
|
|||
if ( !sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp) ) {
|
||||
zm_terminate = true;
|
||||
}
|
||||
frame_count++;
|
||||
// frame_sent = true;
|
||||
}
|
||||
} // end if (!paused) or step or paused
|
||||
} // end if have exceeded buffer or not
|
||||
|
||||
if ( temp_read_index == temp_write_index ) {
|
||||
if (temp_read_index == temp_write_index) {
|
||||
// Go back to live viewing
|
||||
Warning("Rewound over write index, resuming live play");
|
||||
// Clear paused flag
|
||||
|
@ -689,13 +692,13 @@ void MonitorStream::runStream() {
|
|||
delayed = false;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
}
|
||||
} // end if ( buffered_playback && delayed )
|
||||
} // end if (buffered_playback && delayed)
|
||||
|
||||
if ( last_read_index != monitor->shared_data->last_write_index ) {
|
||||
if (last_read_index != monitor->shared_data->last_write_index) {
|
||||
// have a new image to send
|
||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
|
||||
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
|
||||
if ( !paused && !delayed ) {
|
||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
||||
if ((frame_mod == 1) || ((frame_count%frame_mod) == 0)) {
|
||||
if (!paused && !delayed) {
|
||||
last_read_index = monitor->shared_data->last_write_index;
|
||||
Debug(2, "Sending frame index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
|
||||
index, frame_mod, frame_count, paused, delayed);
|
||||
|
@ -710,9 +713,8 @@ void MonitorStream::runStream() {
|
|||
zm_terminate = true;
|
||||
break;
|
||||
}
|
||||
//frame_sent = true;
|
||||
//
|
||||
if ( frame_count == 0 ) {
|
||||
frame_count++;
|
||||
if (frame_count == 0) {
|
||||
// Chrome will not display the first frame until it receives another.
|
||||
// Firefox is fine. So just send the first frame twice.
|
||||
if ( !sendFrame(image, last_frame_timestamp) ) {
|
||||
|
@ -724,16 +726,18 @@ void MonitorStream::runStream() {
|
|||
|
||||
temp_read_index = temp_write_index;
|
||||
} else {
|
||||
if ( delayed && !buffered_playback ) {
|
||||
if (delayed && !buffered_playback) {
|
||||
Debug(2, "Can't delay when not buffering.");
|
||||
delayed = false;
|
||||
}
|
||||
if ( last_zoom != zoom ) {
|
||||
if (last_zoom != zoom) {
|
||||
Debug(2, "Sending 2 frames because change in zoom %d ?= %d", last_zoom, zoom);
|
||||
if (!sendFrame(paused_image, paused_timestamp))
|
||||
zm_terminate = true;
|
||||
if (!sendFrame(paused_image, paused_timestamp))
|
||||
zm_terminate = true;
|
||||
frame_count++;
|
||||
frame_count++;
|
||||
} else {
|
||||
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
|
||||
if ( actual_delta_time > 5 ) {
|
||||
|
@ -744,17 +748,20 @@ void MonitorStream::runStream() {
|
|||
// Send the next frame
|
||||
if (!sendFrame(paused_image, paused_timestamp))
|
||||
zm_terminate = true;
|
||||
frame_count++;
|
||||
} else {
|
||||
Debug(2, "Would have sent keepalive frame, but had no paused_image");
|
||||
}
|
||||
} // end if actual_delta_time > 5
|
||||
} // end if change in zoom
|
||||
} // end if paused or not
|
||||
} else {
|
||||
frame_count++;
|
||||
} // end if should send frame
|
||||
|
||||
if ( buffered_playback && !paused ) {
|
||||
if ( monitor->shared_data->valid ) {
|
||||
if ( monitor->shared_timestamps[index].tv_sec ) {
|
||||
if (buffered_playback && !paused) {
|
||||
if (monitor->shared_data->valid) {
|
||||
if (monitor->shared_timestamps[index].tv_sec) {
|
||||
int temp_index = temp_write_index%temp_image_buffer_count;
|
||||
Debug(2, "Storing frame %d", temp_index);
|
||||
if ( !temp_image_buffer[temp_index].valid ) {
|
||||
|
@ -772,7 +779,7 @@ void MonitorStream::runStream() {
|
|||
config.jpeg_file_quality
|
||||
);
|
||||
temp_write_index = MOD_ADD(temp_write_index, 1, temp_image_buffer_count);
|
||||
if ( temp_write_index == temp_read_index ) {
|
||||
if (temp_write_index == temp_read_index) {
|
||||
// Go back to live viewing
|
||||
Warning("Exceeded temporary buffer, resuming live play");
|
||||
paused = false;
|
||||
|
@ -786,7 +793,6 @@ void MonitorStream::runStream() {
|
|||
Warning("Unable to store frame as shared memory invalid");
|
||||
}
|
||||
} // end if buffered playback
|
||||
frame_count++;
|
||||
} else {
|
||||
Debug(3, "Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
|
||||
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
|
||||
|
@ -815,16 +821,16 @@ void MonitorStream::runStream() {
|
|||
Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d)",
|
||||
frame_mod, frame_count);
|
||||
}
|
||||
} // end while
|
||||
} // end while ! zm_terminate
|
||||
|
||||
if ( buffered_playback ) {
|
||||
if (buffered_playback) {
|
||||
Debug(1, "Cleaning swap files from %s", swap_path.c_str());
|
||||
struct stat stat_buf;
|
||||
if ( stat(swap_path.c_str(), &stat_buf) < 0 ) {
|
||||
if ( errno != ENOENT ) {
|
||||
struct stat stat_buf = {};
|
||||
if (stat(swap_path.c_str(), &stat_buf) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
Error("Can't stat '%s': %s", swap_path.c_str(), strerror(errno));
|
||||
}
|
||||
} else if ( !S_ISDIR(stat_buf.st_mode) ) {
|
||||
} else if (!S_ISDIR(stat_buf.st_mode)) {
|
||||
Error("Swap image path '%s' is not a directory", swap_path.c_str());
|
||||
} else {
|
||||
char glob_pattern[PATH_MAX] = "";
|
||||
|
@ -832,21 +838,21 @@ void MonitorStream::runStream() {
|
|||
snprintf(glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path.c_str());
|
||||
glob_t pglob;
|
||||
int glob_status = glob(glob_pattern, 0, 0, &pglob);
|
||||
if ( glob_status != 0 ) {
|
||||
if ( glob_status < 0 ) {
|
||||
if (glob_status != 0) {
|
||||
if (glob_status < 0) {
|
||||
Error("Can't glob '%s': %s", glob_pattern, strerror(errno));
|
||||
} else {
|
||||
Debug(1, "Can't glob '%s': %d", glob_pattern, glob_status);
|
||||
}
|
||||
} else {
|
||||
for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) {
|
||||
if ( unlink(pglob.gl_pathv[i]) < 0 ) {
|
||||
for (unsigned int i = 0; i < pglob.gl_pathc; i++) {
|
||||
if (unlink(pglob.gl_pathv[i]) < 0) {
|
||||
Error("Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
globfree(&pglob);
|
||||
if ( rmdir(swap_path.c_str()) < 0 ) {
|
||||
if (rmdir(swap_path.c_str()) < 0) {
|
||||
Error("Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno));
|
||||
}
|
||||
} // end if checking for swap_path
|
||||
|
|
|
@ -41,7 +41,6 @@ class MonitorStream : public StreamBase {
|
|||
time_t ttl;
|
||||
int playback_buffer;
|
||||
bool delayed;
|
||||
int frame_count;
|
||||
|
||||
protected:
|
||||
bool checkSwapPath(const char *path, bool create_path);
|
||||
|
@ -62,9 +61,9 @@ class MonitorStream : public StreamBase {
|
|||
temp_write_index(0),
|
||||
ttl(0),
|
||||
playback_buffer(0),
|
||||
delayed(false),
|
||||
frame_count(0) {
|
||||
}
|
||||
delayed(false)
|
||||
{}
|
||||
|
||||
void setStreamBuffer(int p_playback_buffer) {
|
||||
playback_buffer = p_playback_buffer;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
|
|||
if (max_video_packet_count > 0) {
|
||||
while (packet_counts[video_stream_id] > max_video_packet_count) {
|
||||
Error("Unable to free up older packets. Waiting.");
|
||||
condition.notify_all();
|
||||
condition.wait(lck);
|
||||
if (deleting or zm_terminate)
|
||||
return false;
|
||||
|
@ -179,6 +180,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
// So start at the beginning, counting video packets until the next keyframe.
|
||||
// Then if deleting those packets doesn't break 1 and 2, then go ahead and delete them.
|
||||
if (deleting) return;
|
||||
if (!pktQueue.size()) return;
|
||||
|
||||
if (keep_keyframes and ! (
|
||||
add_packet->packet.stream_index == video_stream_id
|
||||
|
@ -197,7 +199,6 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
return;
|
||||
}
|
||||
std::unique_lock<std::mutex> lck(mutex);
|
||||
if (!pktQueue.size()) return;
|
||||
|
||||
// If analysis_it isn't at the end, we need to keep that many additional packets
|
||||
int tail_count = 0;
|
||||
|
@ -257,15 +258,12 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
++it;
|
||||
delete lp;
|
||||
|
||||
if (it == pktQueue.end()) {
|
||||
Debug(1, "Hit end already");
|
||||
it = pktQueue.begin();
|
||||
} else {
|
||||
// Since we have many packets in the queue, we should NOT be pointing at end so don't need to test for that
|
||||
while (*it != add_packet) {
|
||||
zm_packet = *it;
|
||||
lp = new ZMLockedPacket(zm_packet);
|
||||
if (!lp->trylock()) {
|
||||
Debug(3, "Failed locking packet %d", zm_packet->image_index);
|
||||
delete lp;
|
||||
break;
|
||||
}
|
||||
|
@ -282,17 +280,16 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
next_front = it;
|
||||
}
|
||||
++video_packets_to_delete;
|
||||
Debug(4, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d",
|
||||
video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count);
|
||||
Debug(3, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d",
|
||||
video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count);
|
||||
if (packet_counts[video_stream_id] - video_packets_to_delete <= pre_event_video_packet_count + tail_count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
} // end while
|
||||
}
|
||||
} // end if first packet not locked
|
||||
Debug(1, "Resulting pointing at latest packet? %d, next front points to begin? %d",
|
||||
Debug(1, "Resulting it pointing at latest packet? %d, next front points to begin? %d",
|
||||
( *it == add_packet ),
|
||||
( next_front == pktQueue.begin() )
|
||||
);
|
||||
|
@ -325,6 +322,8 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
void PacketQueue::clear() {
|
||||
deleting = true;
|
||||
condition.notify_all();
|
||||
if (!packet_counts) // special case, not initialised
|
||||
return;
|
||||
Debug(1, "Clearing packetqueue");
|
||||
std::unique_lock<std::mutex> lck(mutex);
|
||||
|
||||
|
@ -662,3 +661,12 @@ void PacketQueue::setPreEventVideoPackets(int p) {
|
|||
pre_event_video_packet_count = 1;
|
||||
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
|
||||
}
|
||||
|
||||
void PacketQueue::notify_all() {
|
||||
condition.notify_all();
|
||||
};
|
||||
|
||||
void PacketQueue::wait() {
|
||||
std::unique_lock<std::mutex> lck(mutex);
|
||||
condition.wait(lck);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,8 @@ class PacketQueue {
|
|||
);
|
||||
bool is_there_an_iterator_pointing_to_packet(const std::shared_ptr<ZMPacket> &zm_packet);
|
||||
void unlock(ZMLockedPacket *lp);
|
||||
void notify_all();
|
||||
void wait();
|
||||
};
|
||||
|
||||
#endif /* ZM_PACKETQUEUE_H */
|
||||
|
|
|
@ -100,7 +100,8 @@ void RemoteCamera::Initialise() {
|
|||
|
||||
int ret = getaddrinfo(host.c_str(), port.c_str(), &hints, &hp);
|
||||
if ( ret != 0 ) {
|
||||
Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) );
|
||||
Error( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) );
|
||||
return;
|
||||
}
|
||||
struct addrinfo *p = nullptr;
|
||||
int addr_count = 0;
|
||||
|
|
|
@ -144,6 +144,14 @@ void RemoteCameraHttp::Initialise() {
|
|||
int RemoteCameraHttp::Connect() {
|
||||
struct addrinfo *p = nullptr;
|
||||
|
||||
if (!hp) {
|
||||
RemoteCamera::Initialise();
|
||||
if (!hp) {
|
||||
Error("Unable to resolve address for remote camera, aborting");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for ( p = hp; p != nullptr; p = p->ai_next ) {
|
||||
sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
|
||||
if ( sd < 0 ) {
|
||||
|
|
|
@ -279,9 +279,8 @@ int main(int argc, char *argv[]) {
|
|||
Warning("Unknown format in %s", videoFifoPath.c_str());
|
||||
}
|
||||
if (videoSource == nullptr) {
|
||||
Error("Unable to create source");
|
||||
Error("Unable to create source for %s", videoFifoPath.c_str());
|
||||
rtspServer->RemoveSession(sessions[monitor->Id()]->GetMediaSessionId());
|
||||
delete sessions[monitor->Id()];
|
||||
sessions.erase(monitor->Id());
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,6 @@ protected:
|
|||
int last_scale;
|
||||
int zoom;
|
||||
int last_zoom;
|
||||
double maxfps;
|
||||
int bitrate;
|
||||
unsigned short last_x, last_y;
|
||||
unsigned short x, y;
|
||||
|
@ -122,8 +121,14 @@ protected:
|
|||
struct timeval now;
|
||||
struct timeval last_comm_update;
|
||||
|
||||
double base_fps;
|
||||
double effective_fps;
|
||||
double maxfps;
|
||||
double base_fps; // Should be capturing fps, hence a rough target
|
||||
double effective_fps; // Target fps after taking max_fps into account
|
||||
double actual_fps; // sliding calculated actual streaming fps achieved
|
||||
struct timeval last_fps_update;
|
||||
int frame_count; // Count of frames sent
|
||||
int last_frame_count; // Used in calculating actual_fps from frame_count - last_frame_count
|
||||
|
||||
int frame_mod;
|
||||
|
||||
double last_frame_sent;
|
||||
|
@ -154,7 +159,6 @@ public:
|
|||
last_scale(DEFAULT_SCALE),
|
||||
zoom(DEFAULT_ZOOM),
|
||||
last_zoom(DEFAULT_ZOOM),
|
||||
maxfps(DEFAULT_MAXFPS),
|
||||
bitrate(DEFAULT_BITRATE),
|
||||
last_x(0),
|
||||
last_y(0),
|
||||
|
@ -166,7 +170,15 @@ public:
|
|||
sd(-1),
|
||||
lock_fd(0),
|
||||
paused(false),
|
||||
step(0)
|
||||
step(0),
|
||||
maxfps(DEFAULT_MAXFPS),
|
||||
base_fps(0.0),
|
||||
effective_fps(0.0),
|
||||
actual_fps(0.0),
|
||||
last_fps_update({}),
|
||||
frame_count(0),
|
||||
last_frame_count(0),
|
||||
frame_mod(1)
|
||||
{
|
||||
memset(&loc_sock_path, 0, sizeof(loc_sock_path));
|
||||
memset(&loc_addr, 0, sizeof(loc_addr));
|
||||
|
@ -174,12 +186,8 @@ public:
|
|||
memset(&rem_addr, 0, sizeof(rem_addr));
|
||||
memset(&sock_path_lock, 0, sizeof(sock_path_lock));
|
||||
|
||||
base_fps = 0.0;
|
||||
effective_fps = 0.0;
|
||||
frame_mod = 1;
|
||||
|
||||
#if HAVE_LIBAVCODEC
|
||||
vid_stream = 0;
|
||||
vid_stream = nullptr;
|
||||
#endif // HAVE_LIBAVCODEC
|
||||
last_frame_sent = 0.0;
|
||||
last_frame_timestamp = {};
|
||||
|
|
84
src/zmu.cpp
84
src/zmu.cpp
|
@ -197,6 +197,7 @@ bool ValidateAccess(User *user, int mon_id, int function) {
|
|||
|
||||
void exit_zmu(int exit_code) {
|
||||
logTerm();
|
||||
dbQueue.stop();
|
||||
zmDbClose();
|
||||
|
||||
exit(exit_code);
|
||||
|
@ -248,7 +249,7 @@ int main(int argc, char *argv[]) {
|
|||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
const char *device = nullptr;
|
||||
std::string device;
|
||||
int mon_id = 0;
|
||||
bool verbose = false;
|
||||
int function = ZMU_BOGUS;
|
||||
|
@ -256,9 +257,16 @@ int main(int argc, char *argv[]) {
|
|||
int image_idx = -1;
|
||||
int scale = -1;
|
||||
int brightness = -1;
|
||||
bool have_brightness = false;
|
||||
|
||||
int contrast = -1;
|
||||
bool have_contrast = false;
|
||||
|
||||
int hue = -1;
|
||||
bool have_hue = false;
|
||||
int colour = -1;
|
||||
bool have_colour = false;
|
||||
|
||||
char *zoneString = nullptr;
|
||||
char *username = nullptr;
|
||||
char *password = nullptr;
|
||||
|
@ -275,13 +283,13 @@ int main(int argc, char *argv[]) {
|
|||
int option_index = 0;
|
||||
|
||||
int c = getopt_long(argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::RWU:P:A:V:T:", long_options, &option_index);
|
||||
if ( c == -1 ) {
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
if ( optarg )
|
||||
if (optarg)
|
||||
device = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
|
@ -295,7 +303,7 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'i':
|
||||
function |= ZMU_IMAGE;
|
||||
if ( optarg )
|
||||
if (optarg)
|
||||
image_idx = atoi(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
|
@ -303,7 +311,7 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
case 't':
|
||||
function |= ZMU_TIME;
|
||||
if ( optarg )
|
||||
if (optarg)
|
||||
image_idx = atoi(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
|
@ -320,7 +328,7 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'z':
|
||||
function |= ZMU_ZONES;
|
||||
if ( optarg )
|
||||
if (optarg)
|
||||
zoneString = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
|
@ -352,23 +360,31 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'B':
|
||||
function |= ZMU_BRIGHTNESS;
|
||||
if ( optarg )
|
||||
if (optarg) {
|
||||
have_brightness = true;
|
||||
brightness = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
function |= ZMU_CONTRAST;
|
||||
if ( optarg )
|
||||
if (optarg) {
|
||||
have_contrast = true;
|
||||
contrast = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
function |= ZMU_HUE;
|
||||
if ( optarg )
|
||||
if (optarg) {
|
||||
have_hue = true;
|
||||
hue = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
function |= ZMU_COLOUR;
|
||||
if ( optarg )
|
||||
if (optarg) {
|
||||
have_colour = true;
|
||||
colour = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
username = optarg;
|
||||
|
@ -408,7 +424,7 @@ int main(int argc, char *argv[]) {
|
|||
Usage();
|
||||
}
|
||||
|
||||
if ( device && !(function&ZMU_QUERY) ) {
|
||||
if ( !device.empty() && !(function&ZMU_QUERY) ) {
|
||||
fprintf(stderr, "Error, -d option cannot be used with this option\n");
|
||||
Usage();
|
||||
}
|
||||
|
@ -643,60 +659,60 @@ int main(int argc, char *argv[]) {
|
|||
monitor->DumpSettings(monString, verbose);
|
||||
printf("%s\n", monString);
|
||||
}
|
||||
if ( function & ZMU_BRIGHTNESS ) {
|
||||
if ( verbose ) {
|
||||
if ( brightness >= 0 )
|
||||
if (function & ZMU_BRIGHTNESS) {
|
||||
if (verbose) {
|
||||
if (have_brightness)
|
||||
printf("New brightness: %d\n", monitor->actionBrightness(brightness));
|
||||
else
|
||||
printf("Current brightness: %d\n", monitor->actionBrightness());
|
||||
} else {
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( brightness >= 0 )
|
||||
if (have_output) fputc(separator, stdout);
|
||||
if (have_brightness)
|
||||
printf("%d", monitor->actionBrightness(brightness));
|
||||
else
|
||||
printf("%d", monitor->actionBrightness());
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_CONTRAST ) {
|
||||
if ( verbose ) {
|
||||
if ( contrast >= 0 )
|
||||
printf("New brightness: %d\n", monitor->actionContrast(contrast));
|
||||
if (function & ZMU_CONTRAST) {
|
||||
if (verbose) {
|
||||
if (have_contrast)
|
||||
printf("New contrast: %d\n", monitor->actionContrast(contrast));
|
||||
else
|
||||
printf("Current contrast: %d\n", monitor->actionContrast());
|
||||
} else {
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( contrast >= 0 )
|
||||
if (have_output) fputc(separator, stdout);
|
||||
if (have_contrast)
|
||||
printf("%d", monitor->actionContrast(contrast));
|
||||
else
|
||||
printf("%d", monitor->actionContrast());
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_HUE ) {
|
||||
if ( verbose ) {
|
||||
if ( hue >= 0 )
|
||||
if (function & ZMU_HUE) {
|
||||
if (verbose) {
|
||||
if (have_hue)
|
||||
printf("New hue: %d\n", monitor->actionHue(hue));
|
||||
else
|
||||
printf("Current hue: %d\n", monitor->actionHue());
|
||||
} else {
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( hue >= 0 )
|
||||
if (have_output) fputc(separator, stdout);
|
||||
if (have_hue)
|
||||
printf("%d", monitor->actionHue(hue));
|
||||
else
|
||||
printf("%d", monitor->actionHue());
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_COLOUR ) {
|
||||
if ( verbose ) {
|
||||
if ( colour >= 0 )
|
||||
if (function & ZMU_COLOUR) {
|
||||
if (verbose) {
|
||||
if (have_colour)
|
||||
printf("New colour: %d\n", monitor->actionColour(colour));
|
||||
else
|
||||
printf("Current colour: %d\n", monitor->actionColour());
|
||||
} else {
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( colour >= 0 )
|
||||
if (have_output) fputc(separator, stdout);
|
||||
if (have_colour)
|
||||
printf("%d", monitor->actionColour(colour));
|
||||
else
|
||||
printf("%d", monitor->actionColour());
|
||||
|
@ -704,7 +720,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( have_output ) {
|
||||
if (have_output) {
|
||||
printf("\n");
|
||||
}
|
||||
if ( !function ) {
|
||||
|
@ -714,7 +730,7 @@ int main(int argc, char *argv[]) {
|
|||
if ( function & ZMU_QUERY ) {
|
||||
#if ZM_HAS_V4L
|
||||
char vidString[0x10000] = "";
|
||||
bool ok = LocalCamera::GetCurrentSettings(device, vidString, v4lVersion, verbose);
|
||||
bool ok = LocalCamera::GetCurrentSettings(device.c_str(), vidString, v4lVersion, verbose);
|
||||
printf("%s", vidString);
|
||||
exit_zmu(ok ? 0 : -1);
|
||||
#else // ZM_HAS_V4L
|
||||
|
|
|
@ -58,6 +58,14 @@ case $i in
|
|||
PACKAGE_VERSION="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
-x=*|--debbuild-extra=*)
|
||||
DEBBUILD_EXTRA="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
--dput=*)
|
||||
DPUT="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
--default)
|
||||
DEFAULT=YES
|
||||
shift # past argument with no value
|
||||
|
@ -80,7 +88,7 @@ fi;
|
|||
|
||||
if [ "$DISTROS" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
DISTROS="xenial,bionic,focal,groovy,hirsute"
|
||||
DISTROS="xenial,bionic,focal,hirsute,impish"
|
||||
else
|
||||
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||
fi;
|
||||
|
@ -112,6 +120,11 @@ else
|
|||
if [ "$BRANCH" == "" ]; then
|
||||
#REV=$(git rev-list --tags --max-count=1)
|
||||
BRANCH=`git describe --tags $(git rev-list --tags --max-count=1)`;
|
||||
if [ -z "$BRANCH" ]; then
|
||||
# This should only happen in CI environments where tag info isn't available
|
||||
BRANCH=`cat version`
|
||||
echo "Building branch $BRANCH"
|
||||
fi
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
echo "Unable to determine latest stable branch!"
|
||||
exit 0;
|
||||
|
@ -216,9 +229,14 @@ rm -rf .git
|
|||
rm .gitignore
|
||||
cd ../
|
||||
|
||||
if [ ! -e "$DIRECTORY.orig.tar.gz" ]; then
|
||||
|
||||
if [ !-e "$DIRECTORY.orig.tar.gz" ]; then
|
||||
read -p "$DIRECTORY.orig.tar.gz does not exist, create it? [Y/n]"
|
||||
if [[ $REPLY == [yY] ]]; then
|
||||
|
||||
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
|
||||
fi;
|
||||
fi;
|
||||
|
||||
IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
|
||||
echo "Generating package for $DISTRO";
|
||||
|
@ -229,7 +247,7 @@ IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
|
|||
fi;
|
||||
|
||||
# Generate Changlog
|
||||
if [ "$DISTRO" == "focal" ] || [ "$DISTRO" == "buster" ] || [ "$DISTRO" == "hirsute" ]; then
|
||||
if [ "$DISTRO" == "focal" ] || [ "$DISTRO" == "buster" ] || [ "$DISTRO" == "hirsute" ] || [ "$DISTRO" == "impish" ]; then
|
||||
cp -Rpd distros/ubuntu2004 debian
|
||||
elif [ "$DISTRO" == "beowulf" ]
|
||||
then
|
||||
|
@ -285,30 +303,37 @@ zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY
|
|||
EOF
|
||||
fi;
|
||||
|
||||
# Leave the .orig so that we don't pollute it when building deps
|
||||
cd ..
|
||||
if [ $TYPE == "binary" ]; then
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir ./debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD=debuild
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir $DIRECTORY.orig/debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD=debuild
|
||||
else
|
||||
if [ $TYPE == "local" ]; then
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir ./debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD="debuild -i -us -uc -b"
|
||||
else
|
||||
# Source build, don't need build depends.
|
||||
DEBUILD="debuild -S -sa"
|
||||
fi;
|
||||
if [ $TYPE == "local" ]; then
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir $DIRECTORY.orig/debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD="debuild -i -us -uc -b"
|
||||
else
|
||||
# Source build, don't need build depends.
|
||||
DEBUILD="debuild -S -sa"
|
||||
fi;
|
||||
fi;
|
||||
|
||||
cd $DIRECTORY.orig
|
||||
|
||||
if [ "$DEBSIGN_KEYID" != "" ]; then
|
||||
DEBUILD="$DEBUILD -k$DEBSIGN_KEYID"
|
||||
fi
|
||||
# Add any extra options specified on the CLI
|
||||
DEBUILD="$DEBUILD $DEBBUILD_EXTRA"
|
||||
eval $DEBUILD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error status code is: $?"
|
||||
echo "Error status code is: $?"
|
||||
echo "Build failed.";
|
||||
exit $?;
|
||||
fi;
|
||||
|
@ -340,12 +365,14 @@ EOF
|
|||
dput="Y";
|
||||
if [ "$INTERACTIVE" != "no" ]; then
|
||||
read -p "Ready to dput $SC to $PPA ? Y/n...";
|
||||
if [[ "$REPLY" == [yY] ]]; then
|
||||
if [[ "$REPLY" == "" || "$REPLY" == [yY] ]]; then
|
||||
dput $PPA $SC
|
||||
fi;
|
||||
else
|
||||
echo "dputting to $PPA";
|
||||
dput $PPA $SC
|
||||
if [ "$DPUT" != "no" ]; then
|
||||
echo "dputting to $PPA";
|
||||
dput $PPA $SC
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
done; # foreach distro
|
||||
|
|
|
@ -223,7 +223,7 @@ setdebpkgname () {
|
|||
if [ "" == "$VERSION" ]; then
|
||||
export VERSION="${versionfile}~${thedate}.${numcommits}"
|
||||
fi
|
||||
export RELEASE="${DIST}"
|
||||
export RELEASE="${DIST}${PACKAGE_VERSION}"
|
||||
|
||||
checkvars
|
||||
|
||||
|
@ -369,7 +369,7 @@ elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbia
|
|||
setdebpkgname
|
||||
movecrud
|
||||
|
||||
if [ "${DIST}" == "focal" ] || [ "${DIST}" == "groovy" ] || [ "${DIST}" == "hirsuit" ] || [ "${DIST}" == "buster" ]; then
|
||||
if [ "${DIST}" == "bionic" ] || [ "${DIST}" == "focal" ] || [ "${DIST}" == "hirsute" ] || [ "${DIST}" == "impish" ] || [ "${DIST}" == "buster" ] || [ "${DIST}" == "bullseye" ]; then
|
||||
ln -sfT distros/ubuntu2004 debian
|
||||
elif [ "${DIST}" == "beowulf" ]; then
|
||||
ln -sfT distros/beowulf debian
|
||||
|
|
|
@ -5,7 +5,7 @@ if ( empty($_REQUEST['id']) && empty($_REQUEST['eids']) ) {
|
|||
ajaxError('No event id(s) supplied');
|
||||
}
|
||||
|
||||
if ( canView('Events') ) {
|
||||
if ( canView('Events') or canView('Snapshots') ) {
|
||||
switch ( $_REQUEST['action'] ) {
|
||||
case 'video' :
|
||||
if ( empty($_REQUEST['videoFormat']) ) {
|
||||
|
@ -74,10 +74,15 @@ if ( canView('Events') ) {
|
|||
else
|
||||
$exportCompress = false;
|
||||
|
||||
if ( !empty($_REQUEST['exportStructure']) )
|
||||
$exportStructure = $_SESSION['export']['structure'] = $_REQUEST['exportStructure'];
|
||||
else
|
||||
$exportStructure = false;
|
||||
|
||||
session_write_close();
|
||||
|
||||
$exportIds = !empty($_REQUEST['eids']) ? $_REQUEST['eids'] : $_REQUEST['id'];
|
||||
if ( $exportFile = exportEvents(
|
||||
if ($exportFile = exportEvents(
|
||||
$exportIds,
|
||||
(isset($_REQUEST['connkey'])?$_REQUEST['connkey']:''),
|
||||
$exportDetail,
|
||||
|
@ -86,11 +91,14 @@ if ( canView('Events') ) {
|
|||
$exportVideo,
|
||||
$exportMisc,
|
||||
$exportFormat,
|
||||
$exportCompress
|
||||
) )
|
||||
ajaxResponse(array('exportFile'=>$exportFile));
|
||||
else
|
||||
$exportCompress,
|
||||
$exportStructure,
|
||||
(!empty($_REQUEST['exportFile'])?$_REQUEST['exportFile']:'zmExport'),
|
||||
)) {
|
||||
ajaxResponse(array('exportFile'=>$exportFile));
|
||||
} else {
|
||||
ajaxError('Export Failed');
|
||||
}
|
||||
break;
|
||||
case 'download' :
|
||||
require_once(ZM_SKIN_PATH.'/includes/export_functions.php');
|
||||
|
@ -104,7 +112,7 @@ if ( canView('Events') ) {
|
|||
false,#detail
|
||||
false,#frames
|
||||
false,#images
|
||||
$exportVideo,
|
||||
true, #$exportVideo,
|
||||
false,#Misc
|
||||
$exportFormat,
|
||||
false#,#Compress
|
||||
|
|
|
@ -8,21 +8,23 @@ $data = array();
|
|||
// INITIALIZE AND CHECK SANITY
|
||||
//
|
||||
|
||||
if ( !canView('Snapshots') ) $message = 'Insufficient permissions for user '.$user['Username'];
|
||||
if (!canView('Snapshots'))
|
||||
$message = 'Insufficient permissions for user '.$user['Username'];
|
||||
|
||||
if ( empty($_REQUEST['task']) ) {
|
||||
$task = '';
|
||||
if (empty($_REQUEST['task'])) {
|
||||
$message = 'Must specify a task';
|
||||
} else {
|
||||
$task = $_REQUEST['task'];
|
||||
}
|
||||
|
||||
if ( empty($_REQUEST['ids']) ) {
|
||||
if ( isset($_REQUEST['task']) && $_REQUEST['task'] != 'query' ) $message = 'No snapshot id(s) supplied';
|
||||
if (empty($_REQUEST['ids'])) {
|
||||
if ($task != 'query') $message = 'No snapshot id(s) supplied';
|
||||
} else {
|
||||
$eids = $_REQUEST['ids'];
|
||||
$ids = $_REQUEST['ids'];
|
||||
}
|
||||
|
||||
if ( $message ) {
|
||||
if ($message) {
|
||||
ajaxError($message);
|
||||
return;
|
||||
}
|
||||
|
@ -36,15 +38,15 @@ $advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'],
|
|||
|
||||
// Sort specifies the name of the column to sort on
|
||||
$sort = 'Id';
|
||||
if ( isset($_REQUEST['sort']) ) {
|
||||
if (isset($_REQUEST['sort'])) {
|
||||
$sort = $_REQUEST['sort'];
|
||||
}
|
||||
|
||||
// Offset specifies the starting row to return, used for pagination
|
||||
$offset = 0;
|
||||
if ( isset($_REQUEST['offset']) ) {
|
||||
if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) {
|
||||
ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
|
||||
if (isset($_REQUEST['offset'])) {
|
||||
if ((!is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']))) {
|
||||
ZM\Error('Invalid value for offset: '.$_REQUEST['offset']);
|
||||
} else {
|
||||
$offset = $_REQUEST['offset'];
|
||||
}
|
||||
|
@ -56,8 +58,8 @@ $order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc'
|
|||
// Limit specifies the number of rows to return
|
||||
// Set the default to 0 for events view, to prevent an issue with ALL pagination
|
||||
$limit = 0;
|
||||
if ( isset($_REQUEST['limit']) ) {
|
||||
if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
|
||||
if (isset($_REQUEST['limit'])) {
|
||||
if ((!is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']))) {
|
||||
ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
|
||||
} else {
|
||||
$limit = $_REQUEST['limit'];
|
||||
|
@ -68,14 +70,14 @@ if ( isset($_REQUEST['limit']) ) {
|
|||
// MAIN LOOP
|
||||
//
|
||||
|
||||
switch ( $task ) {
|
||||
switch ($task) {
|
||||
case 'delete' :
|
||||
if ( !canEdit('Snapshots') ) {
|
||||
if (!canEdit('Snapshots')) {
|
||||
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $ids as $id ) $data[] = deleteRequest($id);
|
||||
foreach ($ids as $id) $data[] = deleteRequest($id);
|
||||
break;
|
||||
case 'query' :
|
||||
$data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit);
|
||||
|
@ -99,6 +101,7 @@ function deleteRequest($id) {
|
|||
//$message[] = array($id=>'Event is archived, cannot delete it.');
|
||||
} else {
|
||||
$snapshot->delete();
|
||||
$message[] = array($id=>'Snapshot deleted.');
|
||||
}
|
||||
|
||||
return $message;
|
||||
|
|
|
@ -266,7 +266,7 @@ class MonitorsController extends AppController {
|
|||
if ($mToken) {
|
||||
$auth = ' -T '.$mToken;
|
||||
} else if (ZM_AUTH_RELAY == 'hashed') {
|
||||
$auth = ' -A '.calculateAuthHash(ZM_AUTH_HASH_IPS?$_SERVER['REMOTE_ADDR']:'');
|
||||
$auth = ' -A '.calculateAuthHash(''); # Can't do REMOTE_IP because zmu doesn't normally have access to it.
|
||||
} else if (ZM_AUTH_RELAY == 'plain') {
|
||||
# Plain requires the plain text password which must either be in request or stored in session
|
||||
$password = $this->request->query('pass') ? $this->request->query('pass') : $this->request->data('pass');;
|
||||
|
|
|
@ -627,6 +627,29 @@ class Event extends ZM_Object {
|
|||
return 'Unknown reason';
|
||||
}
|
||||
|
||||
function canView($u=null) {
|
||||
global $user;
|
||||
if (!$u) $u=$user;
|
||||
if (!$u) {
|
||||
# auth turned on and not logged in
|
||||
return false;
|
||||
}
|
||||
if (!empty($u['MonitorIds']) ) {
|
||||
if (in_array($this->{'MonitorId'}, explode(',', $u['MonitorIds']))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if ($u['Events'] != 'None') {
|
||||
return true;
|
||||
}
|
||||
if ($u['Snapshots'] != 'None') {
|
||||
# If the event is contained in a snapshot, then we can still view it.
|
||||
if (dbFetchOne('SELECT * FROM Snapshot_Events WHERE EventId=?', $this->Id()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} # end class
|
||||
|
||||
?>
|
||||
|
|
|
@ -10,7 +10,7 @@ require_once('Group.php');
|
|||
$FunctionTypes = null;
|
||||
|
||||
function getMonitorFunctionTypes() {
|
||||
if ( !isset($FunctionTypes ) ) {
|
||||
if (!isset($FunctionTypes)) {
|
||||
$FunctionTypes = array(
|
||||
'None' => translate('FnNone'),
|
||||
'Monitor' => translate('FnMonitor'),
|
||||
|
@ -23,6 +23,21 @@ function getMonitorFunctionTypes() {
|
|||
return $FunctionTypes;
|
||||
}
|
||||
|
||||
$Statuses = null;
|
||||
function getMonitorStatuses() {
|
||||
if (!isset($Statuses)) {
|
||||
$Statuses = array(
|
||||
-1 => 'Unknown',
|
||||
0 => 'Idle',
|
||||
1 => 'PreAlarm',
|
||||
2 => 'Alarm',
|
||||
3 => 'Alert',
|
||||
4 => 'Tape'
|
||||
);
|
||||
}
|
||||
return $Statuses;
|
||||
}
|
||||
|
||||
class Monitor extends ZM_Object {
|
||||
protected static $table = 'Monitors';
|
||||
|
||||
|
@ -126,6 +141,7 @@ class Monitor extends ZM_Object {
|
|||
'Longitude' => null,
|
||||
'RTSPServer' => array('type'=>'boolean', 'default'=>0),
|
||||
'RTSPStreamName' => '',
|
||||
'Importance' => 'Normal',
|
||||
);
|
||||
private $status_fields = array(
|
||||
'Status' => null,
|
||||
|
@ -149,46 +165,46 @@ class Monitor extends ZM_Object {
|
|||
);
|
||||
|
||||
public function Control() {
|
||||
if ( !property_exists($this, 'Control') ) {
|
||||
if ( $this->ControlId() )
|
||||
if (!property_exists($this, 'Control')) {
|
||||
if ($this->ControlId())
|
||||
$this->{'Control'} = Control::find_one(array('Id'=>$this->{'ControlId'}));
|
||||
|
||||
if ( !(property_exists($this, 'Control') and $this->{'Control'}) )
|
||||
if (!(property_exists($this, 'Control') and $this->{'Control'}))
|
||||
$this->{'Control'} = new Control();
|
||||
}
|
||||
return $this->{'Control'};
|
||||
}
|
||||
|
||||
public function Server() {
|
||||
if ( !property_exists($this, 'Server') ) {
|
||||
if ( $this->ServerId() )
|
||||
if (!property_exists($this, 'Server')) {
|
||||
if ($this->ServerId())
|
||||
$this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'}));
|
||||
if ( !property_exists($this, 'Server') ) {
|
||||
if (!property_exists($this, 'Server')) {
|
||||
$this->{'Server'} = new Server();
|
||||
}
|
||||
}
|
||||
return $this->{'Server'};
|
||||
}
|
||||
|
||||
public function __call($fn, array $args){
|
||||
if ( count($args) ) {
|
||||
if ( is_array($this->defaults[$fn]) and $this->defaults[$fn]['type'] == 'set' ) {
|
||||
public function __call($fn, array $args) {
|
||||
if (count($args)) {
|
||||
if (is_array($this->defaults[$fn]) and $this->defaults[$fn]['type'] == 'set') {
|
||||
$this->{$fn} = is_array($args[0]) ? implode(',', $args[0]) : $args[0];
|
||||
} else {
|
||||
$this->{$fn} = $args[0];
|
||||
}
|
||||
}
|
||||
if ( property_exists($this, $fn) ) {
|
||||
if (property_exists($this, $fn)) {
|
||||
return $this->{$fn};
|
||||
} else if ( array_key_exists($fn, $this->defaults) ) {
|
||||
} else if (array_key_exists($fn, $this->defaults)) {
|
||||
if ( is_array($this->defaults[$fn]) ) {
|
||||
return $this->defaults[$fn]['default'];
|
||||
}
|
||||
return $this->defaults[$fn];
|
||||
} else if ( array_key_exists($fn, $this->status_fields) ) {
|
||||
} else if (array_key_exists($fn, $this->status_fields)) {
|
||||
$sql = 'SELECT * FROM `Monitor_Status` WHERE `MonitorId`=?';
|
||||
$row = dbFetchOne($sql, NULL, array($this->{'Id'}));
|
||||
if ( !$row ) {
|
||||
if (!$row) {
|
||||
Warning('Unable to load Monitor status record for Id='.$this->{'Id'}.' using '.$sql);
|
||||
return null;
|
||||
} else {
|
||||
|
@ -197,10 +213,10 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
}
|
||||
return $this->{$fn};
|
||||
} else if ( array_key_exists($fn, $this->summary_fields) ) {
|
||||
} else if (array_key_exists($fn, $this->summary_fields)) {
|
||||
$sql = 'SELECT * FROM `Event_Summaries` WHERE `MonitorId`=?';
|
||||
$row = dbFetchOne($sql, NULL, array($this->{'Id'}));
|
||||
if ( !$row ) {
|
||||
if (!$row) {
|
||||
Warning('Unable to load Event Summary record for Id='.$this->{'Id'}.' using '.$sql);
|
||||
return null;
|
||||
} else {
|
||||
|
@ -218,7 +234,6 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
|
||||
public function getStreamSrc($args, $querySep='&') {
|
||||
|
||||
$streamSrc = $this->Server()->UrlToZMS(
|
||||
ZM_MIN_STREAMING_PORT ?
|
||||
ZM_MIN_STREAMING_PORT+$this->{'Id'} :
|
||||
|
@ -226,8 +241,8 @@ class Monitor extends ZM_Object {
|
|||
|
||||
$args['monitor'] = $this->{'Id'};
|
||||
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
if (ZM_OPT_USE_AUTH) {
|
||||
if (ZM_AUTH_RELAY == 'hashed') {
|
||||
$args['auth'] = generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
$args['user'] = $_SESSION['username'];
|
||||
|
@ -236,24 +251,24 @@ class Monitor extends ZM_Object {
|
|||
$args['user'] = $_SESSION['username'];
|
||||
}
|
||||
}
|
||||
if ( (!isset($args['mode'])) or ( $args['mode'] != 'single' ) ) {
|
||||
if ((!isset($args['mode'])) or ($args['mode'] != 'single')) {
|
||||
$args['connkey'] = $this->connKey();
|
||||
}
|
||||
if ( ZM_RAND_STREAM ) {
|
||||
if (ZM_RAND_STREAM) {
|
||||
$args['rand'] = time();
|
||||
}
|
||||
|
||||
# zms doesn't support width & height, so if no scale is set, default it
|
||||
if ( ! isset($args['scale']) ) {
|
||||
if ( isset($args['width']) and intval($args['width']) ) {
|
||||
if (!isset($args['scale'])) {
|
||||
if (isset($args['width']) and intval($args['width'])) {
|
||||
$args['scale'] = intval((100*intval($args['width']))/$this->ViewWidth());
|
||||
} else if ( isset($args['height']) and intval($args['height']) ) {
|
||||
} else if (isset($args['height']) and intval($args['height'])) {
|
||||
$args['scale'] = intval((100*intval($args['height']))/$this->ViewHeight());
|
||||
}
|
||||
}
|
||||
if ( isset($args['width']) )
|
||||
if (isset($args['width']))
|
||||
unset($args['width']);
|
||||
if ( isset($args['height']) )
|
||||
if (isset($args['height']))
|
||||
unset($args['height']);
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
@ -269,21 +284,21 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
|
||||
public function ViewWidth($new = null) {
|
||||
if ( $new )
|
||||
if ($new)
|
||||
$this->{'Width'} = $new;
|
||||
|
||||
$field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Height' : 'Width';
|
||||
if ( property_exists($this, $field) )
|
||||
if (property_exists($this, $field))
|
||||
return $this->{$field};
|
||||
return $this->defaults[$field];
|
||||
} // end function Width
|
||||
|
||||
public function ViewHeight($new=null) {
|
||||
if ( $new )
|
||||
if ($new)
|
||||
$this->{'Height'} = $new;
|
||||
|
||||
$field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Width' : 'Height';
|
||||
if ( property_exists($this, $field) )
|
||||
if (property_exists($this, $field))
|
||||
return $this->{$field};
|
||||
return $this->defaults[$field];
|
||||
} // end function Height
|
||||
|
@ -296,50 +311,50 @@ class Monitor extends ZM_Object {
|
|||
|
||||
// Validate that it's a valid colour (we seem to allow color names, not just hex).
|
||||
// This also helps prevent XSS.
|
||||
if ( property_exists($this, $field) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) {
|
||||
if (property_exists($this, $field) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) {
|
||||
return $this->{$field};
|
||||
}
|
||||
return $this->defaults[$field];
|
||||
} // end function SignalCheckColour
|
||||
|
||||
public static function find( $parameters = array(), $options = array() ) {
|
||||
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() ) {
|
||||
public static function find_one($parameters = array(), $options = array()) {
|
||||
return ZM_Object::_find_one(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
function zmcControl( $mode=false ) {
|
||||
if ( !(property_exists($this,'Id') and $this->{'Id'}) ) {
|
||||
function zmcControl($mode=false) {
|
||||
if (!(property_exists($this,'Id') and $this->{'Id'})) {
|
||||
Warning('Attempt to control a monitor with no Id');
|
||||
return;
|
||||
}
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ( $this->Type() == 'Local' ) {
|
||||
if ((!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) )) {
|
||||
if ($this->Type() == 'Local') {
|
||||
$zmcArgs = '-d '.$this->{'Device'};
|
||||
} else {
|
||||
$zmcArgs = '-m '.$this->{'Id'};
|
||||
}
|
||||
|
||||
if ( $mode == 'stop' ) {
|
||||
if ($mode == 'stop') {
|
||||
daemonControl('stop', 'zmc', $zmcArgs);
|
||||
} else {
|
||||
if ( $mode == 'restart' ) {
|
||||
if ($mode == 'restart') {
|
||||
daemonControl('stop', 'zmc', $zmcArgs);
|
||||
}
|
||||
if ( $this->{'Function'} != 'None' ) {
|
||||
if ($this->{'Function'} != 'None') {
|
||||
daemonControl('start', 'zmc', $zmcArgs);
|
||||
}
|
||||
}
|
||||
} else if ( $this->ServerId() ) {
|
||||
} else if ($this->ServerId()) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zmc.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
if (ZM_OPT_USE_AUTH) {
|
||||
if (ZM_AUTH_RELAY == 'hashed') {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} else if ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
} else if (ZM_AUTH_RELAY == 'plain') {
|
||||
$url .= '?user='.$_SESSION['username'];
|
||||
$url .= '?pass='.$_SESSION['password'];
|
||||
} else {
|
||||
|
@ -349,13 +364,13 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
Debug('sending command to '.$url);
|
||||
|
||||
$context = stream_context_create();
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
$result = file_get_contents($url, false, $context);
|
||||
if ( $result === FALSE ) { /* Handle error */
|
||||
if ($result === FALSE) { /* Handle error */
|
||||
Error("Error restarting zmc using $url");
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
} catch (Exception $e) {
|
||||
Error("Except $e thrown trying to restart zmc");
|
||||
}
|
||||
} else {
|
||||
|
@ -363,19 +378,19 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
} // end function zmcControl
|
||||
|
||||
public function GroupIds( $new='' ) {
|
||||
if ( $new != '' ) {
|
||||
if ( !is_array($new) ) {
|
||||
public function GroupIds($new='') {
|
||||
if ($new != '') {
|
||||
if (!is_array($new)) {
|
||||
$this->{'GroupIds'} = array($new);
|
||||
} else {
|
||||
$this->{'GroupIds'} = $new;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !property_exists($this, 'GroupIds') ) {
|
||||
if ( property_exists($this, 'Id') and $this->{'Id'} ) {
|
||||
$this->{'GroupIds'} = dbFetchAll('SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=?', 'GroupId', array($this->{'Id'}) );
|
||||
if ( ! $this->{'GroupIds'} )
|
||||
if (!property_exists($this, 'GroupIds')) {
|
||||
if (property_exists($this, 'Id') and $this->{'Id'}) {
|
||||
$this->{'GroupIds'} = dbFetchAll('SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=?', 'GroupId', array($this->{'Id'}));
|
||||
if (!$this->{'GroupIds'})
|
||||
$this->{'GroupIds'} = array();
|
||||
} else {
|
||||
$this->{'GroupIds'} = array();
|
||||
|
@ -385,8 +400,8 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
|
||||
public function delete() {
|
||||
if ( ! $this->{'Id'} ) {
|
||||
Warning("Attempt to delete a monitor without id.");
|
||||
if (!$this->{'Id'}) {
|
||||
Warning('Attempt to delete a monitor without id.');
|
||||
return;
|
||||
}
|
||||
$this->zmcControl('stop');
|
||||
|
@ -394,17 +409,17 @@ class Monitor extends ZM_Object {
|
|||
// If fast deletes are on, then zmaudit will clean everything else up later
|
||||
// If fast deletes are off and there are lots of events then this step may
|
||||
// well time out before completing, in which case zmaudit will still tidy up
|
||||
if ( !ZM_OPT_FAST_DELETE ) {
|
||||
if (!ZM_OPT_FAST_DELETE) {
|
||||
$markEids = dbFetchAll('SELECT Id FROM Events WHERE MonitorId=?', 'Id', array($this->{'Id'}));
|
||||
foreach ($markEids as $markEid)
|
||||
deleteEvent($markEid);
|
||||
|
||||
if ( $this->{'Name'} )
|
||||
if ($this->{'Name'})
|
||||
deletePath(ZM_DIR_EVENTS.'/'.basename($this->{'Name'}));
|
||||
deletePath(ZM_DIR_EVENTS.'/'.$this->{'Id'});
|
||||
$Storage = $this->Storage();
|
||||
if ( $Storage->Path() != ZM_DIR_EVENTS ) {
|
||||
if ( $this->{'Name'} )
|
||||
if ($Storage->Path() != ZM_DIR_EVENTS) {
|
||||
if ($this->{'Name'})
|
||||
deletePath($Storage->Path().'/'.basename($this->{'Name'}));
|
||||
deletePath($Storage->Path().'/'.$this->{'Id'});
|
||||
}
|
||||
|
@ -420,14 +435,14 @@ class Monitor extends ZM_Object {
|
|||
} // end function delete
|
||||
|
||||
public function Storage($new = null) {
|
||||
if ( $new ) {
|
||||
if ($new) {
|
||||
$this->{'Storage'} = $new;
|
||||
}
|
||||
if ( ! ( property_exists($this, 'Storage') and $this->{'Storage'} ) ) {
|
||||
if (!(property_exists($this, 'Storage') and $this->{'Storage'})) {
|
||||
$this->{'Storage'} = isset($this->{'StorageId'}) ?
|
||||
Storage::find_one(array('Id'=>$this->{'StorageId'})) :
|
||||
new Storage(NULL);
|
||||
if ( ! $this->{'Storage'} )
|
||||
if (!$this->{'Storage'})
|
||||
$this->{'Storage'} = new Storage(NULL);
|
||||
}
|
||||
return $this->{'Storage'};
|
||||
|
@ -435,42 +450,42 @@ class Monitor extends ZM_Object {
|
|||
|
||||
public function Source( ) {
|
||||
$source = '';
|
||||
if ( $this->{'Type'} == 'Local' ) {
|
||||
if ($this->{'Type'} == 'Local') {
|
||||
$source = $this->{'Device'}.' ('.$this->{'Channel'}.')';
|
||||
} else if ( $this->{'Type'} == 'Remote' ) {
|
||||
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||
if ( $this->{'Port'} != '80' and $this->{'Port'} != '554' ) {
|
||||
} else if ($this->{'Type'} == 'Remote') {
|
||||
$source = preg_replace('/^.*@/', '', $this->{'Host'});
|
||||
if ($this->{'Port'} != '80' and $this->{'Port'} != '554') {
|
||||
$source .= ':'.$this->{'Port'};
|
||||
}
|
||||
} else if ( $this->{'Type'} == 'VNC' ) {
|
||||
} else if ($this->{'Type'} == 'VNC') {
|
||||
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||
if ( $this->{'Port'} != '5900' ) {
|
||||
if ($this->{'Port'} != '5900') {
|
||||
$source .= ':'.$this->{'Port'};
|
||||
}
|
||||
} else if ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
|
||||
$url_parts = parse_url( $this->{'Path'} );
|
||||
if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) {
|
||||
} else if ($this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite') {
|
||||
$url_parts = parse_url($this->{'Path'});
|
||||
if (ZM_WEB_FILTER_SOURCE == 'Hostname') {
|
||||
# Filter out everything but the hostname
|
||||
if ( isset($url_parts['host']) ) {
|
||||
if (isset($url_parts['host'])) {
|
||||
$source = $url_parts['host'];
|
||||
} else {
|
||||
$source = $this->{'Path'};
|
||||
}
|
||||
} else if ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) {
|
||||
} else if (ZM_WEB_FILTER_SOURCE == 'NoCredentials') {
|
||||
# Filter out sensitive and common items
|
||||
unset($url_parts['user']);
|
||||
unset($url_parts['pass']);
|
||||
#unset($url_parts['scheme']);
|
||||
unset($url_parts['query']);
|
||||
#unset($url_parts['path']);
|
||||
if ( isset($url_parts['port']) and ( $url_parts['port'] == '80' or $url_parts['port'] == '554' ) )
|
||||
if (isset($url_parts['port']) and ($url_parts['port'] == '80' or $url_parts['port'] == '554'))
|
||||
unset($url_parts['port']);
|
||||
$source = unparse_url($url_parts);
|
||||
} else { # Don't filter anything
|
||||
$source = $this->{'Path'};
|
||||
}
|
||||
}
|
||||
if ( $source == '' ) {
|
||||
if ($source == '') {
|
||||
$source = 'Monitor ' . $this->{'Id'};
|
||||
}
|
||||
return $source;
|
||||
|
@ -478,7 +493,6 @@ class Monitor extends ZM_Object {
|
|||
|
||||
public function UrlToIndex($port=null) {
|
||||
return $this->Server()->UrlToIndex($port);
|
||||
//ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null);
|
||||
}
|
||||
|
||||
public function sendControlCommand($command) {
|
||||
|
@ -486,78 +500,78 @@ class Monitor extends ZM_Object {
|
|||
|
||||
$options = array();
|
||||
# Convert from a command line params to an option array
|
||||
foreach ( explode(' ', $command) as $option ) {
|
||||
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
||||
foreach (explode(' ', $command) as $option) {
|
||||
if (preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches)) {
|
||||
$options[$matches[1]] = $matches[2]?$matches[2]:1;
|
||||
} else if ( $option != '' and $option != 'quit' and $option != 'start' and $option != 'stop' ) {
|
||||
} else if ($option != '' and $option != 'quit' and $option != 'start' and $option != 'stop') {
|
||||
Warning("Ignored command for zmcontrol $option in $command");
|
||||
}
|
||||
}
|
||||
if ( !count($options) ) {
|
||||
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
||||
if (!count($options)) {
|
||||
if ($command == 'quit' or $command == 'start' or $command == 'stop') {
|
||||
# These are special as we now run zmcontrol as a daemon through zmdc.
|
||||
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
||||
Debug("Current status $status");
|
||||
if ( $status or ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) ) {
|
||||
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 {
|
||||
Warning("No commands to send to zmcontrol from $command");
|
||||
Warning('No commands to send to zmcontrol from '.$command);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ((!defined('ZM_SERVER_ID')) or (property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}))) {
|
||||
# Local
|
||||
Debug('Trying to send options ' . print_r($options, true));
|
||||
|
||||
$optionString = jsonEncode($options);
|
||||
Debug("Trying to send options $optionString");
|
||||
Debug('Trying to send options '.$optionString);
|
||||
// Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
|
||||
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
if ( $socket < 0 ) {
|
||||
if ($socket < 0) {
|
||||
Error('socket_create() failed: '.socket_strerror($socket));
|
||||
return false;
|
||||
}
|
||||
$sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$this->{'Id'}.'.sock';
|
||||
if ( @socket_connect($socket, $sockFile) ) {
|
||||
if ( !socket_write($socket, $optionString) ) {
|
||||
if (@socket_connect($socket, $sockFile)) {
|
||||
if (!socket_write($socket, $optionString)) {
|
||||
Error('Can\'t write to control socket: '.socket_strerror(socket_last_error($socket)));
|
||||
return false;
|
||||
}
|
||||
} else if ( $command != 'quit' ) {
|
||||
} else if ($command != 'quit') {
|
||||
$command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id '.$this->{'Id'};
|
||||
|
||||
// Can't connect so use script
|
||||
$ctrlOutput = exec(escapeshellcmd($command));
|
||||
}
|
||||
socket_close($socket);
|
||||
} else if ( $this->ServerId() ) {
|
||||
} else if ($this->ServerId()) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
if (ZM_OPT_USE_AUTH) {
|
||||
if (ZM_AUTH_RELAY == 'hashed') {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} else if ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
} else if (ZM_AUTH_RELAY == 'plain') {
|
||||
$url .= '?user='.$_SESSION['username'];
|
||||
$url .= '?pass='.$_SESSION['password'];
|
||||
} else if ( ZM_AUTH_RELAY == 'none' ) {
|
||||
} else if (ZM_AUTH_RELAY == 'none') {
|
||||
$url .= '?user='.$_SESSION['username'];
|
||||
}
|
||||
}
|
||||
Debug("sending command to $url");
|
||||
Debug('sending command to '.$url);
|
||||
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
$result = file_get_contents($url, false, $context);
|
||||
if ( $result === FALSE ) { /* Handle error */
|
||||
if ($result === FALSE) { /* Handle error */
|
||||
Error("Error sending command using $url");
|
||||
return false;
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
} catch (Exception $e) {
|
||||
Error("Exception $e thrown trying to send command to $url");
|
||||
return false;
|
||||
}
|
||||
|
@ -569,18 +583,18 @@ class Monitor extends ZM_Object {
|
|||
} // end function sendControlCommand($mid, $command)
|
||||
|
||||
function Groups($new='') {
|
||||
if ( $new != '' )
|
||||
if ($new != '')
|
||||
$this->Groups = $new;
|
||||
if ( !property_exists($this, 'Groups') ) {
|
||||
if (!property_exists($this, 'Groups')) {
|
||||
$this->Groups = Group::find(array('Id'=>$this->GroupIds()));
|
||||
}
|
||||
return $this->Groups;
|
||||
}
|
||||
function connKey($new='') {
|
||||
if ( $new )
|
||||
if ($new)
|
||||
$this->connKey = $new;
|
||||
if ( !isset($this->connKey) ) {
|
||||
if ( !empty($GLOBALS['connkey']) ) {
|
||||
if (!isset($this->connKey)) {
|
||||
if (!empty($GLOBALS['connkey'])) {
|
||||
$this->connKey = $GLOBALS['connkey'];
|
||||
} else {
|
||||
$this->connKey = generateConnKey();
|
||||
|
@ -596,11 +610,21 @@ class Monitor extends ZM_Object {
|
|||
|
||||
function canView() {
|
||||
global $user;
|
||||
return ( $user && ($user['Monitors'] != 'None') && ( !$this->{'Id'} || visibleMonitor($this->{'Id'}) ));
|
||||
if (!$user) {
|
||||
# auth turned on and not logged in
|
||||
return false;
|
||||
}
|
||||
if (!empty($user['MonitorIds']) ) {
|
||||
# For the purposes of viewing, having specified monitors trumps the Monitor->canView setting.
|
||||
if (in_array($this->{'Id'}, explode(',', $user['MonitorIds']))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ($user['Monitors'] != 'None');
|
||||
}
|
||||
|
||||
function AlarmCommand($cmd) {
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ((!defined('ZM_SERVER_ID')) or (property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}))) {
|
||||
switch ($cmd) {
|
||||
case 'on' : $cmd = ' -a'; break;
|
||||
case 'off': $cmd = ' -c'; break;
|
||||
|
@ -617,7 +641,7 @@ class Monitor extends ZM_Object {
|
|||
return $output;
|
||||
}
|
||||
|
||||
if ( $this->ServerId() ) {
|
||||
if ($this->ServerId()) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = $Server->UrlToApi().'/monitors/alarm/id:'.$this->{'Id'}.'/command:'.$cmd.'.json';
|
||||
|
@ -629,15 +653,15 @@ class Monitor extends ZM_Object {
|
|||
$context = stream_context_create();
|
||||
try {
|
||||
$result = file_get_contents($url, false, $context);
|
||||
if ( $result === FALSE ) { /* Handle error */
|
||||
if ($result === FALSE) { /* Handle error */
|
||||
Error('Error sending command using '.$url);
|
||||
return false;
|
||||
}
|
||||
Debug("Result $result");
|
||||
Debug('Result '.$result);
|
||||
$json = json_decode($result, true);
|
||||
return $json['status'];
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
} catch (Exception $e) {
|
||||
Error("Exception $e thrown trying to send command to $url");
|
||||
return false;
|
||||
}
|
||||
|
@ -647,10 +671,10 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
function TriggerOn() {
|
||||
$output = $this->AlarmCommand('on');
|
||||
if ( $output and preg_match('/Alarmed event id: (\d+)$/', $output, $matches) ) {
|
||||
if ($output and preg_match('/Alarmed event id: (\d+)$/', $output, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
Warning("No event returned from TriggerOn");
|
||||
Warning('No event returned from TriggerOn');
|
||||
}
|
||||
function TriggerOff() {
|
||||
$output = $this->AlarmCommand('off');
|
||||
|
|
|
@ -434,6 +434,11 @@ class ZM_Object {
|
|||
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($this->Id()));
|
||||
if ( !$row ) {
|
||||
Error("Unable to lock $class record for Id=".$this->Id());
|
||||
} else {
|
||||
// row may have been modified since initial load
|
||||
foreach ($row as $k => $v) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
public function remove_from_cache() {
|
||||
|
|
|
@ -30,22 +30,25 @@ class Server extends ZM_Object {
|
|||
return ZM_Object::_find_one(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
public function Hostname( $new = null ) {
|
||||
if ( $new != null )
|
||||
public function Hostname($new = null) {
|
||||
if ($new != null)
|
||||
$this->{'Hostname'} = $new;
|
||||
|
||||
if ( isset( $this->{'Hostname'}) and ( $this->{'Hostname'} != '' ) ) {
|
||||
if (isset( $this->{'Hostname'}) and ($this->{'Hostname'} != '')) {
|
||||
return $this->{'Hostname'};
|
||||
} else if ( $this->Id() ) {
|
||||
return $this->{'Name'};
|
||||
}
|
||||
# This theoretically will match ipv6 addresses as well
|
||||
if ( preg_match( '/^(\[[[:xdigit:]:]+\]|[^:]+)(:[[:digit:]]+)?$/', $_SERVER['HTTP_HOST'], $matches ) ) {
|
||||
return $matches[1];
|
||||
}
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
# This theoretically will match ipv6 addresses as well
|
||||
if ( preg_match( '/^(\[[[:xdigit:]:]+\]|[^:]+)(:[[:digit:]]+)?$/', $_SERVER['HTTP_HOST'], $matches ) ) {
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
$result = explode(':', $_SERVER['HTTP_HOST']);
|
||||
return $result[0];
|
||||
$result = explode(':', $_SERVER['HTTP_HOST']);
|
||||
return $result[0];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public function Protocol( $new = null ) {
|
||||
|
|
|
@ -29,6 +29,7 @@ class Snapshot extends ZM_Object {
|
|||
public function delete() {
|
||||
if ( property_exists($this, 'Id') ) {
|
||||
dbQuery('DELETE FROM `Snapshot_Events` WHERE `SnapshotId`=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM `Snapshots` WHERE `Id`=?', array($this->{'Id'}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,40 +20,39 @@
|
|||
|
||||
global $error_message;
|
||||
// Event scope actions, view permissions only required
|
||||
if ( !canView('Events') ) {
|
||||
if (!canView('Events')) {
|
||||
$error_message = 'You do not have permission to view Events.';
|
||||
ZM\Warning($error_message);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
||||
if ( $action == 'addterm' ) {
|
||||
if (isset($_REQUEST['object']) and ($_REQUEST['object'] == 'filter')) {
|
||||
if ($action == 'addterm') {
|
||||
$_REQUEST['filter'] = addFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
|
||||
} elseif ( $action == 'delterm' ) {
|
||||
} else if ($action == 'delterm') {
|
||||
$_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
|
||||
} else if ( canEdit('Events') ) {
|
||||
|
||||
} else if (canEdit('Events')) {
|
||||
require_once('includes/Filter.php');
|
||||
$filter = new ZM\Filter($_REQUEST['Id']);
|
||||
|
||||
if ( $action == 'delete' ) {
|
||||
if ( !empty($_REQUEST['Id']) ) {
|
||||
if ( $filter->Background() ) {
|
||||
if ($action == 'delete') {
|
||||
if (!empty($_REQUEST['Id'])) {
|
||||
if ($filter->Background()) {
|
||||
$filter->control('stop');
|
||||
}
|
||||
$filter->delete();
|
||||
|
||||
} else {
|
||||
ZM\Error('No filter id passed when deleting');
|
||||
}
|
||||
} else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
|
||||
|
||||
} else if (( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' )) {
|
||||
$_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
|
||||
$_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
|
||||
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
|
||||
|
||||
$_REQUEST['filter']['AutoCopy'] = empty($_REQUEST['filter']['AutoCopy']) ? 0 : 1;
|
||||
$_REQUEST['filter']['AutoCopyTo'] = empty($_REQUEST['filter']['AutoCopyTo']) ? 0 : $_REQUEST['filter']['AutoCopyTo'];
|
||||
$_REQUEST['filter']['AutoMove'] = empty($_REQUEST['filter']['AutoMove']) ? 0 : 1;
|
||||
$_REQUEST['filter']['AutoMoveTo'] = empty($_REQUEST['filter']['AutoMoveTo']) ? 0 : $_REQUEST['filter']['AutoMoveTo'];
|
||||
$_REQUEST['filter']['AutoArchive'] = empty($_REQUEST['filter']['AutoArchive']) ? 0 : 1;
|
||||
$_REQUEST['filter']['AutoVideo'] = empty($_REQUEST['filter']['AutoVideo']) ? 0 : 1;
|
||||
$_REQUEST['filter']['AutoUpload'] = empty($_REQUEST['filter']['AutoUpload']) ? 0 : 1;
|
||||
|
@ -65,44 +64,39 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
$_REQUEST['filter']['Background'] = empty($_REQUEST['filter']['Background']) ? 0 : 1;
|
||||
$_REQUEST['filter']['Concurrent'] = empty($_REQUEST['filter']['Concurrent']) ? 0 : 1;
|
||||
$changes = $filter->changes($_REQUEST['filter']);
|
||||
ZM\Debug('Changes: ' . print_r($changes,true));
|
||||
ZM\Debug('Changes: ' . print_r($changes, true));
|
||||
|
||||
if ($filter->Id() and ($action == 'Save')) {
|
||||
if ($filter->Background()) $filter->control('stop');
|
||||
if (!$filter->save($changes)) {
|
||||
$error_message = $filter->get_last_error();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ( $action == 'execute' ) {
|
||||
if ( count($changes) ) {
|
||||
$filter->Name('_TempFilter'.time());
|
||||
$filter->Id(null);
|
||||
}
|
||||
} else if ( $action == 'SaveAs' ) {
|
||||
$filter->Id(null);
|
||||
}
|
||||
if (!$filter->save($changes)) {
|
||||
$error_message = $filter->get_last_error();
|
||||
return;
|
||||
}
|
||||
if (count($changes)) {
|
||||
if ($filter->Id() and ($action == 'Save') and $filter->Background()) {
|
||||
$filter->control('stop');
|
||||
} else if ($action == 'execute') {
|
||||
# If there are changes use a temp filter to do the execute
|
||||
$filter->Name('_TempFilter'.time());
|
||||
$filter->Id(null);
|
||||
} else if ($action == 'SaveAs') {
|
||||
$filter->Id(null);
|
||||
}
|
||||
if (!$filter->save($changes)) {
|
||||
$error_message = $filter->get_last_error();
|
||||
return;
|
||||
}
|
||||
// We update the request id so that the newly saved filter is auto-selected
|
||||
$_REQUEST['Id'] = $filter->Id();
|
||||
} # end if changes
|
||||
|
||||
// We update the request id so that the newly saved filter is auto-selected
|
||||
$_REQUEST['Id'] = $filter->Id();
|
||||
}
|
||||
|
||||
if ( $action == 'execute' ) {
|
||||
if ($action == 'execute') {
|
||||
$filter->execute();
|
||||
if ( count($changes) )
|
||||
if (count($changes)) {
|
||||
$filter->delete();
|
||||
|
||||
$view = 'events';
|
||||
} else if ( $filter->Background() ) {
|
||||
$filter->Id(null);
|
||||
}
|
||||
} else if ($filter->Background()) {
|
||||
$filter->control('start');
|
||||
}
|
||||
global $redirect;
|
||||
$redirect = '?view=filter'.$filter->querystring('filter', '&');
|
||||
|
||||
} else if ( $action == 'control' ) {
|
||||
} else if ($action == 'control') {
|
||||
if ( $_REQUEST['command'] == 'start'
|
||||
or $_REQUEST['command'] == 'stop'
|
||||
or $_REQUEST['command'] == 'restart'
|
||||
|
@ -114,5 +108,4 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
} // end if save or execute
|
||||
} // end if canEdit(Events)
|
||||
} // end if object == filter
|
||||
|
||||
?>
|
||||
|
|
|
@ -47,9 +47,12 @@ if ( $action == 'create' ) {
|
|||
$monitor = new ZM\Monitor($monitor_id);
|
||||
$monitor->TriggerOff();
|
||||
}
|
||||
$dbConn->beginTransaction();
|
||||
foreach ( $snapshot->Events() as $event ) {
|
||||
$event->lock();
|
||||
$event->save(array('Archived'=>1));
|
||||
}
|
||||
$dbConn->commit();
|
||||
$redirect = '?view=snapshot&id='.$snapshot->Id();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
require_once('logger.php');
|
||||
|
||||
function buildControlCommand($monitor) {
|
||||
$ctrlCommand = '';
|
||||
$control = $monitor->Control();
|
||||
|
@ -218,7 +220,7 @@ function buildControlCommand($monitor) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Error('Invalid control parameter: ' . $_REQUEST['control'] );
|
||||
ZM\Error('Invalid control parameter: ' . $_REQUEST['control'] );
|
||||
}
|
||||
} elseif ( isset($_REQUEST['x']) && isset($_REQUEST['y']) ) {
|
||||
if ( $_REQUEST['control'] == 'moveMap' ) {
|
||||
|
|
|
@ -192,8 +192,6 @@ $user = null;
|
|||
if ( isset($_REQUEST['view']) )
|
||||
$view = detaintPath($_REQUEST['view']);
|
||||
|
||||
# Add CSP Headers
|
||||
$cspNonce = bin2hex(zm_random_bytes(16));
|
||||
|
||||
$request = null;
|
||||
if ( isset($_REQUEST['request']) )
|
||||
|
@ -294,8 +292,11 @@ if ( $request ) {
|
|||
return;
|
||||
}
|
||||
|
||||
# Add CSP Headers
|
||||
$cspNonce = bin2hex(zm_random_bytes(16));
|
||||
if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
|
||||
ob_start();
|
||||
CSPHeaders($view, $cspNonce);
|
||||
foreach ( $includeFiles as $includeFile ) {
|
||||
if ( !file_exists($includeFile) )
|
||||
ZM\Fatal("View '$view' does not exist");
|
||||
|
@ -309,9 +310,7 @@ if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
|
|||
foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile )
|
||||
require_once $includeFile;
|
||||
}
|
||||
|
||||
CSPHeaders($view, $cspNonce);
|
||||
ob_end_flush();
|
||||
while (ob_get_level() > 0) ob_end_flush();
|
||||
}
|
||||
// If the view is missing or the view still returned error with the user logged in,
|
||||
// then it is not recoverable.
|
||||
|
|
|
@ -348,16 +348,16 @@ $SLANG = array(
|
|||
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
|
||||
'File' => 'Fichier',
|
||||
'Filter' => 'Filtre', // Added - 2015-04-18
|
||||
'FilterArchiveEvents' => 'Archiver',
|
||||
'FilterDeleteEvents' => 'Effacer',
|
||||
'FilterEmailEvents' => 'Envoyer les détails par email',
|
||||
'FilterArchiveEvents' => 'Archiver les évènements',
|
||||
'FilterDeleteEvents' => 'Effacer les évènements',
|
||||
'FilterEmailEvents' => 'Envoyer les évènements par email',
|
||||
'FilterExecuteEvents' => 'Exécuter une commande',
|
||||
'FilterLog' => 'Filtre', // Added - 2015-04-18
|
||||
'FilterMessageEvents' => 'Envoyer les détails par message',
|
||||
'FilterMessageEvents' => 'Envoyer les évènements par message',
|
||||
'FilterMoveEvents' => 'Move all matches', // Added - 2018-08-30
|
||||
'FilterPx' => 'Filtre Px',
|
||||
'FilterUnset' => 'Vous devez spécifier une largeur et une hauteur de filtre',
|
||||
'FilterUpdateDiskSpace'=> 'Update used disk space', // Added - 2018-08-30
|
||||
'FilterUpdateDiskSpace'=> 'Mies à jour de l\'espace disque utilisé', // Added - 2018-08-30
|
||||
'FilterUploadEvents' => 'Transférer',
|
||||
'FilterVideoEvents' => 'Créer vidéo',
|
||||
'Filters' => 'Filtres',
|
||||
|
|
|
@ -84,7 +84,7 @@ $SLANG = array(
|
|||
'AddNewControl' => 'Aggiungi nuovo Controllo',
|
||||
'AddNewMonitor' => 'Aggiungi nuovo Monitor',
|
||||
'AddNewServer' => 'Aggiungi nuovo Server', // Added - 2018-08-30
|
||||
'AddNewStorage' => 'Aggiungi nuovo Storage', // Added - 2018-08-30
|
||||
'AddNewStorage' => 'Aggiungi nuovo Archivio', // Added - 2018-08-30
|
||||
'AddNewUser' => 'Aggiungi nuovo Utente',
|
||||
'AddNewZone' => 'Aggiungi nuova Zona',
|
||||
'Alarm' => 'Allarme',
|
||||
|
@ -95,49 +95,49 @@ $SLANG = array(
|
|||
'AlarmMaximumFPS' => 'FPS massimi durante l\'allarme',
|
||||
'AlarmPx' => 'Pixel Allarme',
|
||||
'AlarmRGBUnset' => 'Devi settare un colore RGB di allarme',
|
||||
'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18
|
||||
'AlarmRefImageBlendPct'=> 'Riferimento Allarme - Fusione Immagine %', // Added - 2015-04-18
|
||||
'Alert' => 'Attenzione',
|
||||
'All' => 'Tutto',
|
||||
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
|
||||
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
|
||||
'AnalysisFPS' => 'Analisi FPS', // Added - 2015-07-22
|
||||
'AnalysisUpdateDelay' => 'Intervallo aggiornamento analisi', // Added - 2015-07-23
|
||||
'Apply' => 'Applica',
|
||||
'ApplyingStateChange' => 'Sto applicando le modifiche',
|
||||
'ArchArchived' => 'Archiviato',
|
||||
'ArchUnarchived' => 'Non archiviato',
|
||||
'ArchUnarchived' => 'Non Archiviato',
|
||||
'Archive' => 'Archivio',
|
||||
'Archived' => 'Archiviato',
|
||||
'Area' => 'Area',
|
||||
'AreaUnits' => 'Area (px/%)',
|
||||
'AttrAlarmFrames' => 'Immagini in Allarme',
|
||||
'AttrAlarmFrames' => 'Immagini Allarme',
|
||||
'AttrArchiveStatus' => 'Stato Archivio',
|
||||
'AttrAvgScore' => 'Punteggio medio',
|
||||
'AttrAvgScore' => 'Punteggio Medio',
|
||||
'AttrCause' => 'Causa',
|
||||
'AttrDiskBlocks' => 'Blocchi del Disco',
|
||||
'AttrDiskPercent' => 'Percentuale del Disco',
|
||||
'AttrDiskSpace' => 'Disk Space', // Added - 2018-08-30
|
||||
'AttrDiskBlocks' => 'Blocchi disco',
|
||||
'AttrDiskPercent' => 'Percentuale disco',
|
||||
'AttrDiskSpace' => 'Spazio disco', // Added - 2018-08-30
|
||||
'AttrDuration' => 'Durata',
|
||||
'AttrEndDate' => 'End Date', // Added - 2018-08-30
|
||||
'AttrEndDateTime' => 'End Date/Time', // Added - 2018-08-30
|
||||
'AttrEndTime' => 'End Time', // Added - 2018-08-30
|
||||
'AttrEndWeekday' => 'End Weekday', // Added - 2018-08-30
|
||||
'AttrFilterServer' => 'Server Filter is Running On', // Added - 2018-08-30
|
||||
'AttrFilterServer' => 'Filtro attivo su Server', // Added - 2018-08-30
|
||||
'AttrFrames' => 'Immagini',
|
||||
'AttrId' => 'Id',
|
||||
'AttrMaxScore' => 'Punteggio massimo',
|
||||
'AttrMaxScore' => 'Punteggio Massimo',
|
||||
'AttrMonitorId' => 'Id Monitor',
|
||||
'AttrMonitorName' => 'Nome Monitor',
|
||||
'AttrMonitorServer' => 'Server Monitor is Running On', // Added - 2018-08-30
|
||||
'AttrMonitorServer' => 'Monitor attivo su Server', // Added - 2018-08-30
|
||||
'AttrName' => 'Nome',
|
||||
'AttrNotes' => 'Note',
|
||||
'AttrStartDate' => 'Start Date', // Added - 2018-08-30
|
||||
'AttrStartDateTime' => 'Start Date/Time', // Added - 2018-08-30
|
||||
'AttrStartTime' => 'Start Time', // Added - 2018-08-30
|
||||
'AttrStartWeekday' => 'Start Weekday', // Added - 2018-08-30
|
||||
'AttrStateId' => 'Run State', // Added - 2018-08-30
|
||||
'AttrStorageArea' => 'Storage Area', // Added - 2018-08-30
|
||||
'AttrStorageServer' => 'Server Hosting Storage', // Added - 2018-08-30
|
||||
'AttrSystemLoad' => 'System Load',
|
||||
'AttrTotalScore' => 'Punteggio totale',
|
||||
'AttrStartDate' => 'Inizio - Data', // Added - 2018-08-30
|
||||
'AttrStartDateTime' => 'Inizio - Data/orario', // Added - 2018-08-30
|
||||
'AttrStartTime' => 'Inizio - Orario', // Added - 2018-08-30
|
||||
'AttrStartWeekday' => 'Inizio - Giorno della settimana', // Added - 2018-08-30
|
||||
'AttrStateId' => 'Stato Esecuzione', // Added - 2018-08-30
|
||||
'AttrStorageArea' => 'Area Archiviazione', // Added - 2018-08-30
|
||||
'AttrStorageServer' => 'Server Archiviazione remota', // Added - 2018-08-30
|
||||
'AttrSystemLoad' => 'Carico Sistema',
|
||||
'AttrTotalScore' => 'Punteggio Totale',
|
||||
'Auto' => 'Auto',
|
||||
'AutoStopTimeout' => 'Auto Stop Timeout',
|
||||
'Available' => 'Disponibile', // Added - 2009-03-31
|
||||
|
@ -181,56 +181,56 @@ $SLANG = array(
|
|||
'BlobPx' => 'Blob Px',
|
||||
'BlobSizes' => 'Dimensioni Blob',
|
||||
'Blobs' => 'Blobs',
|
||||
'Brightness' => 'Luminosità',
|
||||
'Brightness' => 'Luminosità',
|
||||
'Buffer' => 'Buffer', // Added - 2015-04-18
|
||||
'Buffers' => 'Buffers',
|
||||
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
|
||||
'CanAutoFocus' => 'Puo\' Auto Focus',
|
||||
'CanAutoGain' => 'Puo\' Auto Gains',
|
||||
'CanAutoIris' => 'Puo\' Auto Iris',
|
||||
'CanAutoWhite' => 'Puo\' Auto bil bianco',
|
||||
'CanAutoZoom' => 'Puo\' Auto Zoom',
|
||||
'CanFocus' => 'Puo\' Fuoco',
|
||||
'CanFocusAbs' => 'Puo\' Fuoco Assoluto',
|
||||
'CanFocusCon' => 'Puo\' Fuoco Continuo ',
|
||||
'CanFocusRel' => 'Puo\' Fuoco Relativo',
|
||||
'CanGain' => 'Puo\' Gain ',
|
||||
'CanGainAbs' => 'Puo\' Gain Assoluto',
|
||||
'CanGainCon' => 'Puo\' Gain Continuo ',
|
||||
'CanGainRel' => 'Puo\' Gain Relativo',
|
||||
'CanIris' => 'Puo\' Iris',
|
||||
'CanIrisAbs' => 'Puo\' Iris Assoluto',
|
||||
'CanIrisCon' => 'Puo\' Iris Continuo ',
|
||||
'CanIrisRel' => 'Puo\' Iris Relativo',
|
||||
'CanMove' => 'Puo\' Mov.',
|
||||
'CanMoveAbs' => 'Puo\' Mov. Assoluto',
|
||||
'CanMoveCon' => 'Puo\' Mov. Continuo ',
|
||||
'CanMoveDiag' => 'Puo\' Mov. Diagonale ',
|
||||
'CanMoveMap' => 'Puo\' Mov Mappato',
|
||||
'CanMoveRel' => 'Puo\' Mov. Relativo',
|
||||
'CanPan' => 'Puo\' Pan' ,
|
||||
'CanReset' => 'Puo\' Reset',
|
||||
'CanReboot' => 'Can Reboot',
|
||||
'CanSetPresets' => 'Puo\' impostare preset',
|
||||
'CanSleep' => 'Puo\' andare in sleep',
|
||||
'CanTilt' => 'Puo\' Tilt',
|
||||
'CanWake' => 'Puo\' essere riattivato',
|
||||
'CanWhite' => 'Puo\' bilanciare il bianco',
|
||||
'CanWhiteAbs' => 'Puo\' bilanciare il bianco assoluto',
|
||||
'CanWhiteBal' => 'Puo\' bilanciare il bianco',
|
||||
'CanWhiteCon' => 'Puo\' bilanciare il bianco Continuo',
|
||||
'CanWhiteRel' => 'Puo\' bilanciare il bianco Relativo',
|
||||
'CanZoom' => 'Puo\' Zoom',
|
||||
'CanZoomAbs' => 'Puo\' Zoom Assoluto',
|
||||
'CanZoomCon' => 'Puo\' Zoom Continuo',
|
||||
'CanZoomRel' => 'Puo\' Zoom Relativo',
|
||||
'CanAutoFocus' => 'Può Auto Focus',
|
||||
'CanAutoGain' => 'Può Auto Gains',
|
||||
'CanAutoIris' => 'Può Auto Iris',
|
||||
'CanAutoWhite' => 'Può Auto bil bianco',
|
||||
'CanAutoZoom' => 'Può Auto Zoom',
|
||||
'CanFocus' => 'Può Fuoco',
|
||||
'CanFocusAbs' => 'Può Fuoco Assoluto',
|
||||
'CanFocusCon' => 'Può Fuoco Continuo ',
|
||||
'CanFocusRel' => 'Può Fuoco Relativo',
|
||||
'CanGain' => 'Può Gain ',
|
||||
'CanGainAbs' => 'Può Gain Assoluto',
|
||||
'CanGainCon' => 'Può Gain Continuo ',
|
||||
'CanGainRel' => 'Può Gain Relativo',
|
||||
'CanIris' => 'Può Iris',
|
||||
'CanIrisAbs' => 'Può Iris Assoluto',
|
||||
'CanIrisCon' => 'Può Iris Continuo ',
|
||||
'CanIrisRel' => 'Può Iris Relativo',
|
||||
'CanMove' => 'Può Mov.',
|
||||
'CanMoveAbs' => 'Può Mov. Assoluto',
|
||||
'CanMoveCon' => 'Può Mov. Continuo ',
|
||||
'CanMoveDiag' => 'Può Mov. Diagonale ',
|
||||
'CanMoveMap' => 'Può Mov Mappato',
|
||||
'CanMoveRel' => 'Può Mov. Relativo',
|
||||
'CanPan' => 'Può Pan' ,
|
||||
'CanReset' => 'Può Reset',
|
||||
'CanReboot' => 'Può Riavviare',
|
||||
'CanSetPresets' => 'Può impostare preset',
|
||||
'CanSleep' => 'Può andare in sleep',
|
||||
'CanTilt' => 'Può inclinare',
|
||||
'CanWake' => 'Può essere riattivato',
|
||||
'CanWhite' => 'Può bilanciare il bianco',
|
||||
'CanWhiteAbs' => 'Può bilanciare il bianco assoluto',
|
||||
'CanWhiteBal' => 'Può bilanciare il bianco',
|
||||
'CanWhiteCon' => 'Può bilanciare il bianco Continuo',
|
||||
'CanWhiteRel' => 'Può bilanciare il bianco Relativo',
|
||||
'CanZoom' => 'Può Zoom',
|
||||
'CanZoomAbs' => 'Può Zoom Assoluto',
|
||||
'CanZoomCon' => 'Può Zoom Continuo',
|
||||
'CanZoomRel' => 'Può Zoom Relativo',
|
||||
'Cancel' => 'Annulla',
|
||||
'CancelForcedAlarm' => 'Annulla Allarme Forzato',
|
||||
'CaptureHeight' => 'Altezza img catturata',
|
||||
'CaptureMethod' => 'Metodo di cattura', // Added - 2009-02-08
|
||||
'CapturePalette' => 'Paletta img catturata',
|
||||
'CaptureResolution' => 'Risoluzione di cattura', // Added - 2015-04-18
|
||||
'CaptureWidth' => 'Larghezza img Catturata',
|
||||
'CaptureHeight' => 'Altezza Cattura Immagine',
|
||||
'CaptureMethod' => 'Metodo Cattura Immagine', // Added - 2009-02-08
|
||||
'CapturePalette' => 'Tavolozza Cattura Immagine',
|
||||
'CaptureResolution' => 'Risoluzione Cattura Immagine', // Added - 2015-04-18
|
||||
'CaptureWidth' => 'Larghezza Cattura Immagine',
|
||||
'Cause' => 'Causa',
|
||||
'CheckMethod' => 'Metodo di Controllo Allarme',
|
||||
'ChooseDetectedCamera' => 'Scegli telecamera rilevata', // Added - 2009-03-31
|
||||
|
@ -238,13 +238,13 @@ $SLANG = array(
|
|||
'ChooseLogFormat' => 'Scegli un formato di registro', // Added - 2011-06-17
|
||||
'ChooseLogSelection' => 'Scegli una selezione del registro', // Added - 2011-06-17
|
||||
'ChoosePreset' => 'Scegli Preset',
|
||||
'Clear' => 'Clear', // Added - 2011-06-16
|
||||
'CloneMonitor' => 'Clone', // Added - 2018-08-30
|
||||
'Clear' => 'Pulisci', // Added - 2011-06-16
|
||||
'CloneMonitor' => 'Clona', // Added - 2018-08-30
|
||||
'Close' => 'Chiudi',
|
||||
'Colour' => 'Colori',
|
||||
'Command' => 'Comando',
|
||||
'Component' => 'Component', // Added - 2011-06-16
|
||||
'ConcurrentFilter' => 'Run filter concurrently', // Added - 2018-08-30
|
||||
'ConcurrentFilter' => 'Esegui filtro contemporaneamente', // Added - 2018-08-30
|
||||
'Config' => 'Configura',
|
||||
'ConfiguredFor' => 'Configurato per',
|
||||
'ConfirmDeleteEvents' => 'Sei sicuro di voler cancellare gli eventi selezionati',
|
||||
|
@ -257,29 +257,29 @@ $SLANG = array(
|
|||
'Contrast' => 'Contrasto',
|
||||
'Control' => 'Controllo',
|
||||
'ControlAddress' => 'Indirizzo di controllo',
|
||||
'ControlCap' => 'Capacita\' di controllo',
|
||||
'ControlCaps' => 'Capacita\' di controllo',
|
||||
'ControlCap' => 'Capacità di controllo',
|
||||
'ControlCaps' => 'Capacità di controllo',
|
||||
'ControlDevice' => 'Dispositivo di controllo',
|
||||
'ControlType' => 'Tipo Controllo',
|
||||
'Controllable' => 'Controllabile',
|
||||
'Current' => 'Current', // Added - 2015-04-18
|
||||
'Current' => 'Corrente', // Added - 2015-04-18
|
||||
'Cycle' => 'Cicla',
|
||||
'CycleWatch' => 'Vista Ciclica',
|
||||
'DateTime' => 'Date/Time', // Added - 2011-06-16
|
||||
'DateTime' => 'Data/Orario', // Added - 2011-06-16
|
||||
'Day' => 'Giorno',
|
||||
'Debug' => 'Debug',
|
||||
'DefaultRate' => 'Default Rate',
|
||||
'DefaultRate' => 'Rateo predefinito',
|
||||
'DefaultScale' => 'Scala di default',
|
||||
'DefaultView' => 'Visualizzazione di default',
|
||||
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
|
||||
'Delay' => 'Delay', // Added - 2015-04-18
|
||||
'DefaultView' => 'Visualizzazione predefinita',
|
||||
'Deinterlacing' => 'Deinterlacciamento', // Added - 2015-04-18
|
||||
'Delay' => 'Ritardo', // Added - 2015-04-18
|
||||
'Delete' => 'Elimina',
|
||||
'DeleteAndNext' => 'Elimina & Prossimo',
|
||||
'DeleteAndPrev' => 'Elimina & Precedente',
|
||||
'DeleteAndNext' => 'Elimina e Prossimo',
|
||||
'DeleteAndPrev' => 'Elimina e Precedente',
|
||||
'DeleteSavedFilter' => 'Elimina il filtro salvato',
|
||||
'Description' => 'Descrizione',
|
||||
'DetectedCameras' => 'Telecamere Rilevate', // Added - 2009-03-31
|
||||
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
|
||||
'DetectedProfiles' => 'Profili Rilevati', // Added - 2015-04-18
|
||||
'Device' => 'Periferica', // Added - 2009-02-08
|
||||
'DeviceChannel' => 'Canale Periferica',
|
||||
'DeviceFormat' => 'Formato',
|
||||
|
@ -287,18 +287,18 @@ $SLANG = array(
|
|||
'DevicePath' => 'Percorso Dispositivo',
|
||||
'Devices' => 'Dispositivi',
|
||||
'Dimensions' => 'Dimensioni',
|
||||
'DisableAlarms' => 'Disabil Allarme',
|
||||
'DisableAlarms' => 'Disabilita Allarme',
|
||||
'Disk' => 'Utilizzo Disco',
|
||||
'Display' => 'Display', // Added - 2011-01-30
|
||||
'Displaying' => 'Displaying', // Added - 2011-06-16
|
||||
'DoNativeMotionDetection'=> 'Do Native Motion Detection',
|
||||
'Display' => 'Mostra', // Added - 2011-01-30
|
||||
'Displaying' => 'Visualizzazione', // Added - 2011-06-16
|
||||
'DoNativeMotionDetection'=> 'Attiva Motion Detection Nativo',
|
||||
'Donate' => 'Donate,per favore',
|
||||
'DonateAlready' => 'No, ho gia donato... ',
|
||||
'DonateEnticement' => 'Stai usando ZoneMinder da un po\' di tempo e spero che tu lo stia trovando utile per la sicurezza di casa tua o del tuo posto di lavoro..Anche se ZoneMinder e\' distribuito liberamente come software libero,costa soldi sia svilupparlo che supportarlo. Se preferisci che questo software continui ad avere supporto e sviluppo in futuro allora considera l\idea di fare una piccola donazione. Donare e\' ovviamente opzionale, ma apprezzato e puoi donare quanto vuoi,quel poco o tanto che tu desideri.<br><br>Se hai voglia per cortesia seleziona l\'opzione sotto o punta il tuo browser a https://zoneminder.com/donate/ .<br><br>Grazie per usare ZoneMinder e non dimenticare di visitare il forum in ZoneMinder.com se cerchi supporto o hai suggerimenti riguardo a come rendere migliore Zoneminder.',
|
||||
'DonateEnticement' => 'Stai usando ZoneMinder da un pò di tempo e spero che tu lo stia trovando utile per la sicurezza di casa tua o del tuo posto di lavoro..Anche se ZoneMinder e\' distribuito liberamente come software libero,costa soldi sia svilupparlo che supportarlo. Se preferisci che questo software continui ad avere supporto e sviluppo in futuro allora considera l\idea di fare una piccola donazione. Donare e\' ovviamente opzionale, ma apprezzato e puoi donare quanto vuoi,quel poco o tanto che tu desideri.<br><br>Se hai voglia per cortesia seleziona l\'opzione sotto o punta il tuo browser a https://zoneminder.com/donate/ .<br><br>Grazie per usare ZoneMinder e non dimenticare di visitare il forum in ZoneMinder.com se cerchi supporto o hai suggerimenti riguardo a come rendere migliore Zoneminder.',
|
||||
'DonateRemindDay' => 'Non ancora, ricordamelo ancora tra 1 giorno',
|
||||
'DonateRemindHour' => 'Non ancora, ricordamelo ancora tra 1 ora',
|
||||
'DonateRemindMonth' => 'Non ancora, ricordamelo ancora tra 1 mese',
|
||||
'DonateRemindNever' => 'No, io non voglio donare, non lo faro\' mai',
|
||||
'DonateRemindNever' => 'No, io non voglio donare, non lo farò mai',
|
||||
'DonateRemindWeek' => 'Non ancora, ricordamelo ancora tra 1 settimana',
|
||||
'DonateYes' => 'Si,mi piacerebbe donare qualcosa ora',
|
||||
'Download' => 'Scarica',
|
||||
|
@ -325,24 +325,24 @@ $SLANG = array(
|
|||
'Execute' => 'Esegui',
|
||||
'Exif' => 'Includi dati EXIF nell\'immagine', // Added - 2018-08-30
|
||||
'Export' => 'Esporta',
|
||||
'ExportDetails' => 'Esp. dettagli eventi',
|
||||
'ExportFailed' => 'Esp. Fallita ',
|
||||
'ExportFormat' => 'Formato File Esp. ',
|
||||
'ExportDetails' => 'Esporta dettagli eventi',
|
||||
'ExportFailed' => 'Esportazione Fallita ',
|
||||
'ExportFormat' => 'Formato File Esportazione',
|
||||
'ExportFormatTar' => 'Tar',
|
||||
'ExportFormatZip' => 'Zip',
|
||||
'ExportFrames' => 'Dettagli frame espo.',
|
||||
'ExportFrames' => 'Esporta dettagli immagini',
|
||||
'ExportImageFiles' => 'Esporta le immagini',
|
||||
'ExportLog' => 'Export Log', // Added - 2011-06-17
|
||||
'ExportMiscFiles' => 'Esporto Altri file (se presenti)',
|
||||
'ExportLog' => 'Esporta Log', // Added - 2011-06-17
|
||||
'ExportMiscFiles' => 'Esporta Altri file (se presenti)',
|
||||
'ExportOptions' => 'Opzioni Esportazione',
|
||||
'ExportSucceeded' => 'Export completata con successo', // Added - 2009-02-08
|
||||
'ExportVideoFiles' => 'Esporto File Video (se presenti)',
|
||||
'Exporting' => 'In corso.',
|
||||
'ExportSucceeded' => 'Esportazione completata con successo', // Added - 2009-02-08
|
||||
'ExportVideoFiles' => 'Esporta File Video (se presenti)',
|
||||
'Exporting' => 'In corso',
|
||||
'FPS' => 'fps',
|
||||
'FPSReportInterval' => 'Intervallo Report FPS',
|
||||
'FTP' => 'FTP',
|
||||
'Far' => 'Lontano',
|
||||
'FastForward' => 'Fast Forward',
|
||||
'FastForward' => 'Avanzamento veloce',
|
||||
'Feed' => 'Feed',
|
||||
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
|
||||
'File' => 'File',
|
||||
|
@ -351,7 +351,7 @@ $SLANG = array(
|
|||
'FilterDeleteEvents' => 'Elimina gli eventi',
|
||||
'FilterEmailEvents' => 'Invia dettagli via email',
|
||||
'FilterExecuteEvents' => 'Esegui un comando',
|
||||
'FilterLog' => 'Filter log', // Added - 2015-04-18
|
||||
'FilterLog' => 'Filtra log', // Added - 2015-04-18
|
||||
'FilterMessageEvents' => 'Invia dettagli tramite messaggio',
|
||||
'FilterMoveEvents' => 'Sposta tutti gli eventi', // Added - 2018-08-30
|
||||
'FilterPx' => 'Px Filtro',
|
||||
|
@ -363,12 +363,12 @@ $SLANG = array(
|
|||
'First' => 'Primo',
|
||||
'FlippedHori' => 'ribaltato orizzontale',
|
||||
'FlippedVert' => 'ribaltato verticale',
|
||||
'FnMocord' => 'Mocord', // Added 2013.08.16.
|
||||
'FnModect' => 'Modect', // Added 2013.08.16.
|
||||
'FnMonitor' => 'Monitor', // Added 2013.08.16.
|
||||
'FnNodect' => 'Nodect', // Added 2013.08.16.
|
||||
'FnNone' => 'None', // Added 2013.08.16.
|
||||
'FnRecord' => 'Record', // Added 2013.08.16.
|
||||
'FnMocord' => 'Mocord - Registrazione continua (con evidenziazione eventi)', // Added 2013.08.16.
|
||||
'FnModect' => 'Modect - MOtion DEteCTtion (registrazione su rilevamento movimento)', // Added 2013.08.16.
|
||||
'FnMonitor' => 'Monitor - Visualizza Live', // Added 2013.08.16.
|
||||
'FnNodect' => 'Nodect - No DEteCTtion (registrazione su evento esterno)', // Added 2013.08.16.
|
||||
'FnNone' => 'None - Nessuno (Monitor disabilitato)', // Added 2013.08.16.
|
||||
'FnRecord' => 'Record - Registrazione continua', // Added 2013.08.16.
|
||||
'Focus' => 'Focus',
|
||||
'ForceAlarm' => 'Forza Allarme',
|
||||
'Format' => 'Formato',
|
||||
|
@ -379,7 +379,7 @@ $SLANG = array(
|
|||
'Frames' => 'Immagini',
|
||||
'Func' => 'Funz',
|
||||
'Function' => 'Funzione',
|
||||
'Gain' => 'Gain',
|
||||
'Gain' => 'Guadagno',
|
||||
'General' => 'Generale',
|
||||
'GenerateDownload' => 'Genera download', // Added - 2018-08-30
|
||||
'GenerateVideo' => 'Genera video',
|
||||
|
@ -388,19 +388,19 @@ $SLANG = array(
|
|||
'Grey' => 'Grigio',
|
||||
'Group' => 'Gruppo',
|
||||
'Groups' => 'Gruppi',
|
||||
'HasFocusSpeed' => 'Ha velocita\' di focus',
|
||||
'HasGainSpeed' => 'Ha velocita\' di guadagno',
|
||||
'HasFocusSpeed' => 'Ha velocità di focus',
|
||||
'HasGainSpeed' => 'Ha velocità di guadagno',
|
||||
'HasHomePreset' => 'Ha posizioni di present',
|
||||
'HasIrisSpeed' => 'Ha velocota\' di iris',
|
||||
'HasPanSpeed' => 'Ha velocita\' di Pan',
|
||||
'HasIrisSpeed' => 'Ha velocità di iris',
|
||||
'HasPanSpeed' => 'Ha velocità di Pan',
|
||||
'HasPresets' => 'Ha preset',
|
||||
'HasTiltSpeed' => 'Ha velocita\' di Tilt',
|
||||
'HasTiltSpeed' => 'Ha velocità di Tilt',
|
||||
'HasTurboPan' => 'Ha il Turbo Pan',
|
||||
'HasTurboTilt' => 'Ha il Turbo Tilt',
|
||||
'HasWhiteSpeed' => 'Ha velocita\' di bilanciamento del bianco',
|
||||
'HasZoomSpeed' => 'Ha velocita\' di zoom',
|
||||
'HasWhiteSpeed' => 'Ha velocità di bilanciamento del bianco',
|
||||
'HasZoomSpeed' => 'Ha velocità di zoom',
|
||||
'High' => 'Alta',
|
||||
'HighBW' => 'Banda Alta',
|
||||
'HighBW' => 'Banda Alta',
|
||||
'Home' => 'Home',
|
||||
'Hostname' => 'Nome Host', // Added - 2018-08-30
|
||||
'Hour' => 'Ora',
|
||||
|
@ -414,7 +414,7 @@ $SLANG = array(
|
|||
'In' => 'In',
|
||||
'Include' => 'Includi',
|
||||
'Inverted' => 'Invertito',
|
||||
'Iris' => 'Iris',
|
||||
'Iris' => 'Iride',
|
||||
'KeyString' => 'Stringa Chiave',
|
||||
'Label' => 'Etichetta',
|
||||
'Language' => 'Linguaggio',
|
||||
|
@ -438,39 +438,39 @@ $SLANG = array(
|
|||
'Logout' => 'Logout',
|
||||
'Logs' => 'Logs', // Added - 2011-06-17
|
||||
'Low' => 'Bassa',
|
||||
'LowBW' => 'Banda Bassa',
|
||||
'LowBW' => 'Banda Bassa',
|
||||
'Main' => 'Principale',
|
||||
'Man' => 'Man',
|
||||
'Manual' => 'Manuale',
|
||||
'Mark' => 'Seleziona',
|
||||
'Max' => 'Massima',
|
||||
'MaxBandwidth' => 'Banda Massima',
|
||||
'MaxBrScore' => 'Punteggio<br/>Massimo',
|
||||
'MaxBrScore' => 'Punteggio Massimo',
|
||||
'MaxFocusRange' => 'Massimo range del focus',
|
||||
'MaxFocusSpeed' => 'Massima velocita\' del focus',
|
||||
'MaxFocusSpeed' => 'Massima velocità del focus',
|
||||
'MaxFocusStep' => 'Massimo step del focus',
|
||||
'MaxGainRange' => 'Massimo range del guadagno',
|
||||
'MaxGainSpeed' => 'Massima velocita\' del guadagno',
|
||||
'MaxGainSpeed' => 'Massima velocità del guadagno',
|
||||
'MaxGainStep' => 'Massimo step del guadagno',
|
||||
'MaxIrisRange' => 'Massima range dell\'Iris',
|
||||
'MaxIrisSpeed' => 'Massima velocita\' dell\'Iris',
|
||||
'MaxIrisStep' => 'Massimo step dell\'Iris',
|
||||
'MaxIrisRange' => 'Massima range dell\'Iride',
|
||||
'MaxIrisSpeed' => 'Massima velocità dell\'Iride',
|
||||
'MaxIrisStep' => 'Massimo step dell\'Iride',
|
||||
'MaxPanRange' => 'Massimo range del pan',
|
||||
'MaxPanSpeed' => 'Massima velocita\' del tilt',
|
||||
'MaxPanSpeed' => 'Massima velocità del tilt',
|
||||
'MaxPanStep' => 'Massimo step del pan',
|
||||
'MaxTiltRange' => 'Massimo range del tilt',
|
||||
'MaxTiltSpeed' => 'Massima velocita\' del tilt',
|
||||
'MaxTiltSpeed' => 'Massima velocità del tilt',
|
||||
'MaxTiltStep' => 'Massimo passo del tilt',
|
||||
'MaxWhiteRange' => 'Massimo range del bilanciamento del bianco',
|
||||
'MaxWhiteSpeed' => 'Massima velocita\' del bilanciamento del bianco',
|
||||
'MaxWhiteSpeed' => 'Massima velocità del bilanciamento del bianco',
|
||||
'MaxWhiteStep' => 'Massimo Step del bilanciamento del bianco',
|
||||
'MaxZoomRange' => 'Massimo range dello zoom',
|
||||
'MaxZoomSpeed' => 'Massima velocita\' dello zoom',
|
||||
'MaxZoomSpeed' => 'Massima velocità dello zoom',
|
||||
'MaxZoomStep' => 'Massimo step dello zoom',
|
||||
'MaximumFPS' => 'Massimi FPS',
|
||||
'Medium' => 'Media',
|
||||
'MediumBW' => 'Banda Media',
|
||||
'Message' => 'Message', // Added - 2011-06-16
|
||||
'MediumBW' => 'Larghezza Banda Media',
|
||||
'Message' => 'Messaggio', // Added - 2011-06-16
|
||||
'MinAlarmAreaLtMax' => 'L\'area minima dell\'allarme deve essere minore di quella massima',
|
||||
'MinAlarmAreaUnset' => 'Devi specificare il numero minimo di pixel per l\'allarme',
|
||||
'MinBlobAreaLtMax' => 'L\'area di blob minima deve essere minore dell\'area di blob massima',
|
||||
|
@ -482,47 +482,47 @@ $SLANG = array(
|
|||
'MinFilterAreaUnset' => 'Devi specificare il numero minimo di pixel per il filtro',
|
||||
'MinFilterLtMinAlarm' => 'L\'area minima di filtro deve essere minore o uguale dell\area minima di allarme',
|
||||
'MinFocusRange' => 'Range minimo del Focus',
|
||||
'MinFocusSpeed' => 'Velocita\' minima del Focus',
|
||||
'MinFocusSpeed' => 'Velocità minima del Focus',
|
||||
'MinFocusStep' => 'Minimo step del Focus',
|
||||
'MinGainRange' => 'Minimo range del Guadagno',
|
||||
'MinGainSpeed' => 'Velocita\' minima del Guadagno',
|
||||
'MinGainSpeed' => 'Velocità minima del Guadagno',
|
||||
'MinGainStep' => 'Step minimo del guadagno',
|
||||
'MinIrisRange' => 'Range minimo dell\'Iris',
|
||||
'MinIrisSpeed' => 'Velocita\' minima dell\'Iris',
|
||||
'MinIrisStep' => 'Step minimo dell\'Iris',
|
||||
'MinPanRange' => 'Range minimo del pan',
|
||||
'MinPanSpeed' => 'Velocita\' minima del Pan',
|
||||
'MinIrisRange' => 'Range minimo dell\'Iride',
|
||||
'MinIrisSpeed' => 'Velocità minima dell\'Iride',
|
||||
'MinIrisStep' => 'Step minimo dell\'Iride',
|
||||
'MinPanRange' => 'Range minimo del Pan',
|
||||
'MinPanSpeed' => 'Velocità minima del Pan',
|
||||
'MinPanStep' => 'Step minimo del Pan',
|
||||
'MinPixelThresLtMax' => 'I pixel minimi della soglia devono essere minori dei pixel massimi della soglia',
|
||||
'MinPixelThresUnset' => 'Devi specificare una soglia minima di pixel', // Added - 2009-02-08
|
||||
'MinTiltRange' => 'Range minimo del Tilt',
|
||||
'MinTiltSpeed' => 'Velocita\' minima del Tilt',
|
||||
'MinTiltSpeed' => 'Velocità minima del Tilt',
|
||||
'MinTiltStep' => 'Step minimo del Tilt',
|
||||
'MinWhiteRange' => 'Range minimo del bilanciamento del bianco',
|
||||
'MinWhiteSpeed' => 'Velocita\' minima del bialnciamento del bianco',
|
||||
'MinWhiteSpeed' => 'Velocità minima del bialnciamento del bianco',
|
||||
'MinWhiteStep' => 'Minimo step del bilanciamento del bianco',
|
||||
'MinZoomRange' => 'Range minimo dello zoom',
|
||||
'MinZoomSpeed' => 'Velocita\' minima dello zoom',
|
||||
'MinZoomSpeed' => 'Velocità minima dello zoom',
|
||||
'MinZoomStep' => 'Step minimo dello zoom',
|
||||
'Misc' => 'Altro',
|
||||
'Mode' => 'Modalità', // Added - 2015-04-18
|
||||
'Monitor' => 'Monitor',
|
||||
'MonitorIds' => 'Monitor Ids',
|
||||
'MonitorIds' => 'Monitor Ids',
|
||||
'MonitorPreset' => 'Monitor Presenti',
|
||||
'MonitorPresetIntro' => 'Selezionare un appropriato pre settaggio dalla lista riportata qui sotto.<br><br>Per favore notare che questo potrebbe sovrascrivere ogni valore che hai già configurato su questo monitor.<br><br>',
|
||||
'MonitorProbe' => 'Prova Monitor', // Added - 2009-03-31
|
||||
'MonitorProbeIntro' => 'The list below shows detected analog and network cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.<br/><br/>', // Added - 2009-03-31
|
||||
'Monitors' => 'Monitors',
|
||||
'Montage' => 'Montaggio',
|
||||
'MontageReview' => 'Montage Review', // Added - 2018-08-30
|
||||
'MontageReview' => 'Revisione del montaggio', // Added - 2018-08-30
|
||||
'Month' => 'Mese',
|
||||
'More' => 'More', // Added - 2011-06-16
|
||||
'MotionFrameSkip' => 'Motion Frame Skip',
|
||||
'More' => 'Più', // Added - 2011-06-16
|
||||
'MotionFrameSkip' => 'Salta/scarta fotogramma',
|
||||
'Move' => 'Sposta',
|
||||
'Mtg2widgrd' => '2-wide grid', // Added 2013.08.15.
|
||||
'Mtg3widgrd' => '3-wide grid', // Added 2013.08.15.
|
||||
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
|
||||
'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15.
|
||||
'Mtg2widgrd' => 'Griglia 2 colonne', // Added 2013.08.15.
|
||||
'Mtg3widgrd' => 'Griglia 3 colonne', // Added 2013.08.15.
|
||||
'Mtg3widgrx' => 'Griglia 3 colonne, scalata, ingrandita su allarme', // Added 2013.08.15.
|
||||
'Mtg4widgrd' => 'Griglia 4 colonne', // Added 2013.08.15.
|
||||
'MtgDefault' => 'Predefinito', // Added 2013.08.15.
|
||||
'MustBeGe' => 'deve essere superiore a',
|
||||
'MustBeLe' => 'deve essere inferiore o pari a',
|
||||
|
@ -550,7 +550,7 @@ $SLANG = array(
|
|||
'NoneAvailable' => 'Nessuno disponibile',
|
||||
'Normal' => 'Normale',
|
||||
'Notes' => 'Note',
|
||||
'NumPresets' => 'Num Presets',
|
||||
'NumPresets' => 'Num redefiniti',
|
||||
'Off' => 'Off',
|
||||
'On' => 'On',
|
||||
'OnvifCredentialsIntro'=> 'Fornire nome utente e password per la telecamera selezionata.<br/>Se non è stato creato alcun utente per la videocamera, l\'utente qui indicato verrà creato con la password specificata.<br/><br/>', // Added - 2015-04-18
|
||||
|
@ -589,7 +589,7 @@ $SLANG = array(
|
|||
'Paths' => 'Percorsi',
|
||||
'Pause' => 'Pause',
|
||||
'Phone' => 'Telefono',
|
||||
'PhoneBW' => 'Banda Tel',
|
||||
'PhoneBW' => 'Banda Tel',
|
||||
'Pid' => 'PID', // Added - 2011-06-16
|
||||
'PixelDiff' => 'Pixel Diff',
|
||||
'Pixels' => 'pixels',
|
||||
|
@ -598,18 +598,18 @@ $SLANG = array(
|
|||
'PleaseWait' => 'Attendere prego',
|
||||
'Plugins' => 'Plugins',
|
||||
'Point' => 'Punto',
|
||||
'PostEventImageBuffer' => 'Buffer di immagini Dopo Evento',
|
||||
'PreEventImageBuffer' => 'Buffer di immagini Pre Evento',
|
||||
'PostEventImageBuffer' => 'Buffer immagini Dopo Evento',
|
||||
'PreEventImageBuffer' => 'Buffer immagini Pre Evento',
|
||||
'PreserveAspect' => 'Preserve Aspect Ratio',
|
||||
'Preset' => 'Preset',
|
||||
'Presets' => 'Presets',
|
||||
'Presets' => 'Predefiniti',
|
||||
'Prev' => 'Prec',
|
||||
'Probe' => 'Prova la telecamera', // Added - 2009-03-31
|
||||
'ProfileProbe' => 'Prova lo stream', // Added - 2015-04-18
|
||||
'ProfileProbeIntro' => 'L\'elenco seguente mostra i profili di streaming esistenti della telecamera selezionata.<br/><br/>Selezionare la voce desiderata dall\'elenco seguente.<br/><br/>Si noti che ZoneMinder non è in grado di configurare profili aggiuntivi e che la scelta di una telecamera qui può sovrascrivere qualsiasi valore già configurato per il monitor corrente.<br/><br/>', // Added - 2015-04-18
|
||||
'Progress' => 'Progresso', // Added - 2015-04-18
|
||||
'Protocol' => 'Protocollo',
|
||||
'RTSPDescribe' => 'Use RTSP Response Media URL', // Added - 2018-08-30
|
||||
'RTSPDescribe' => 'Usa URL multimediale di risposta RTSP', // Added - 2018-08-30
|
||||
'RTSPTransport' => 'RTSP Transport Protocol', // Added - 2018-08-30
|
||||
'Rate' => 'Velocità',
|
||||
'Real' => 'Reale',
|
||||
|
@ -622,18 +622,18 @@ $SLANG = array(
|
|||
'RemoteHostName' => 'Nome dell\'Host Remoto',
|
||||
'RemoteHostPath' => 'Percorso dell\'Host Remoto',
|
||||
'RemoteHostPort' => 'Porta dell\'Host Remoto',
|
||||
'RemoteHostSubPath' => 'SubPath host remoto', // Added - 2009-02-08
|
||||
'RemoteHostSubPath' => 'Percorso secondario dell\'Host remoto', // Added - 2009-02-08
|
||||
'RemoteImageColours' => 'Colori delle immagini Remote',
|
||||
'RemoteMethod' => 'Metodo Remoto', // Added - 2009-02-08
|
||||
'RemoteProtocol' => 'Protocollo Remoto', // Added - 2009-02-08
|
||||
'Rename' => 'Rinomina',
|
||||
'Replay' => 'Replay',
|
||||
'ReplayAll' => 'All Events',
|
||||
'ReplayGapless' => 'Gapless Events',
|
||||
'ReplaySingle' => 'Single Event',
|
||||
'ReportEventAudit' => 'Rapporto Eventi di controllo', // Added - 2018-08-30
|
||||
'Reset' => 'Resetta',
|
||||
'ResetEventCounts' => 'Resetta Contatore Eventi',
|
||||
'Replay' => 'Riproduci',
|
||||
'ReplayAll' => 'Tutti gli Eventi',
|
||||
'ReplayGapless' => 'Eventi continui',
|
||||
'ReplaySingle' => 'Evento singolo',
|
||||
'ReportEventAudit' => 'Controllo Eventi', // Added - 2018-08-30
|
||||
'Reset' => 'Reset',
|
||||
'ResetEventCounts' => 'Reset Contatore Eventi',
|
||||
'Restart' => 'Riavvia',
|
||||
'Restarting' => 'Sto riavviando',
|
||||
'RestrictedCameraIds' => 'Camera Ids Riservati',
|
||||
|
@ -644,7 +644,7 @@ $SLANG = array(
|
|||
'RotateLeft' => 'Ruota a Sinista',
|
||||
'RotateRight' => 'Ruota a Destra',
|
||||
'RunLocalUpdate' => 'Eseguire zmupdate.pl per l\'aggiornamento', // Added - 2011-05-25
|
||||
'RunMode' => 'Modalita\' funzionamento',
|
||||
'RunMode' => 'Modalità funzionamento',
|
||||
'RunState' => 'Stato di funzionamento',
|
||||
'Running' => 'Attivo',
|
||||
'Save' => 'Salva',
|
||||
|
@ -671,69 +671,69 @@ $SLANG = array(
|
|||
'Size' => 'grandezza',
|
||||
'SkinDescription' => 'Cambia la skin predefinita per questo computer', // Added - 2011-01-30
|
||||
'Sleep' => 'Sleep',
|
||||
'SortAsc' => 'Cresc',
|
||||
'SortAsc' => 'Crescente',
|
||||
'SortBy' => 'Ordina per',
|
||||
'SortDesc' => 'Decr',
|
||||
'SortDesc' => 'Decrescente',
|
||||
'Source' => 'Sorgente',
|
||||
'SourceColours' => 'Colori della Sorgente', // Added - 2009-02-08
|
||||
'SourcePath' => 'Percorso della Sorgente', // Added - 2009-02-08
|
||||
'SourceType' => 'Tipo Sorgente',
|
||||
'Speed' => 'Velocita\'',
|
||||
'SpeedHigh' => 'Alta Velocita\'',
|
||||
'SpeedLow' => 'Bassa Velocita\'',
|
||||
'SpeedMedium' => 'Media Velocita\'',
|
||||
'SpeedTurbo' => 'Turbo Velocita\'',
|
||||
'Speed' => 'Velocità',
|
||||
'SpeedHigh' => 'Alta Velocità',
|
||||
'SpeedLow' => 'Bassa Velocità',
|
||||
'SpeedMedium' => 'Media Velocità',
|
||||
'SpeedTurbo' => 'Turbo Velocità',
|
||||
'Start' => 'Avvia',
|
||||
'State' => 'Stato',
|
||||
'Stats' => 'Statistiche',
|
||||
'Status' => 'Stato',
|
||||
'StatusConnected' => 'Capturing', // Added - 2018-08-30
|
||||
'StatusNotRunning' => 'Not Running', // Added - 2018-08-30
|
||||
'StatusRunning' => 'Not Capturing', // Added - 2018-08-30
|
||||
'StatusUnknown' => 'Unknown', // Added - 2018-08-30
|
||||
'StatusConnected' => 'Registrazione in corso', // Added - 2018-08-30
|
||||
'StatusNotRunning' => 'Non in esecuzione', // Added - 2018-08-30
|
||||
'StatusRunning' => 'Registrazione in pausa', // Added - 2018-08-30
|
||||
'StatusUnknown' => 'Sconosciuto', // Added - 2018-08-30
|
||||
'Step' => 'Passo',
|
||||
'StepBack' => 'Passo indietro',
|
||||
'StepForward' => 'Passo avanti',
|
||||
'StepLarge' => 'Lungo passo',
|
||||
'StepMedium' => 'Medio passo',
|
||||
'StepNone' => 'No passo',
|
||||
'StepSmall' => 'Piccolo passo',
|
||||
'Stills' => 'Foto',
|
||||
'StepLarge' => 'Passo lungo',
|
||||
'StepMedium' => 'Passo medio',
|
||||
'StepNone' => 'Nessun passo',
|
||||
'StepSmall' => 'Passo piccolo',
|
||||
'Stills' => 'Immagini fisse',
|
||||
'Stop' => 'Stop',
|
||||
'Stopped' => 'Inattivo',
|
||||
'StorageArea' => 'Area di salvataggio', // Added - 2018-08-30
|
||||
'StorageScheme' => 'Scheme', // Added - 2018-08-30
|
||||
'Stream' => 'Flusso',
|
||||
'StreamReplayBuffer' => 'Stream Replay Image Buffer',
|
||||
'StorageArea' => 'Area Archiviazione', // Added - 2018-08-30
|
||||
'StorageScheme' => 'Schema Archiviazione', // Added - 2018-08-30
|
||||
'Stream' => 'Stream',
|
||||
'StreamReplayBuffer' => 'Buffer immagini riproduzione stream',
|
||||
'Submit' => 'Accetta',
|
||||
'System' => 'Sistema',
|
||||
'SystemLog' => 'Log di sistema', // Added - 2011-06-16
|
||||
'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18
|
||||
'TargetColorspace' => 'Spazio dei colori obiettivo', // Added - 2015-04-18
|
||||
'Tele' => 'Tele',
|
||||
'Thumbnail' => 'Anteprima',
|
||||
'Tilt' => 'Tilt',
|
||||
'Tilt' => 'Tilt (Inclinazione)',
|
||||
'Time' => 'Ora',
|
||||
'TimeDelta' => 'Tempo di Delta',
|
||||
'TimeStamp' => 'Time Stamp',
|
||||
'TimeDelta' => 'Differenza orario',
|
||||
'TimeStamp' => 'Sovraimpressione data/orario',
|
||||
'Timeline' => 'Linea Temporale',
|
||||
'TimelineTip1' => 'Passa il mouse sul grafico per visualizzare un\'immagine dell\'istantanea e i dettagli dell\'evento.', // Added 2013.08.15.
|
||||
'TimelineTip2' => 'Fai clic sulle sezioni colorate del grafico o sull\'immagine per visualizzare l\'evento.', // Added 2013.08.15.
|
||||
'TimelineTip3' => 'Fare clic sullo sfondo per ingrandire un periodo di tempo più piccolo basato sul clic.', // Added 2013.08.15.
|
||||
'TimelineTip4' => 'Utilizzare i controlli seguenti per ridurre o spostarsi avanti e indietro nell\'intervallo di tempo.', // Added 2013.08.15.
|
||||
'Timestamp' => 'Timestamp',
|
||||
'TimestampLabelFormat' => 'Formato etichetta timestamp',
|
||||
'Timestamp' => 'Sovraimpressione data/orario',
|
||||
'TimestampLabelFormat' => 'Formato etichetta Sovraimpressione data/orario',
|
||||
'TimestampLabelSize' => 'Dimensione carattere', // Added - 2018-08-30
|
||||
'TimestampLabelX' => 'coordinata X etichetta',
|
||||
'TimestampLabelY' => 'coordinata Y etichetta',
|
||||
'Today' => 'Oggi ',
|
||||
'Tools' => 'Strumenti',
|
||||
'Total' => 'Totale', // Added - 2011-06-16
|
||||
'TotalBrScore' => 'Punteggio<br/>Totale',
|
||||
'TrackDelay' => 'Track Delay',
|
||||
'TrackMotion' => 'Track Motion',
|
||||
'Triggers' => 'Triggers',
|
||||
'TurboPanSpeed' => 'Velocita\' Turbo Pan',
|
||||
'TurboTiltSpeed' => 'Velocita\' Turbo Tilt',
|
||||
'TotalBrScore' => 'Punteggio Totale',
|
||||
'TrackDelay' => 'Ritardo traccia',
|
||||
'TrackMotion' => 'Segui movimento',
|
||||
'Triggers' => 'Inneschi/Interruttori',
|
||||
'TurboPanSpeed' => 'Velocità Turbo Pan',
|
||||
'TurboTiltSpeed' => 'Velocità Turbo Tilt',
|
||||
'Type' => 'Tipo',
|
||||
'Unarchive' => 'Togli dall\'archivio',
|
||||
'Undefined' => 'Non specificato', // Added - 2009-02-08
|
||||
|
@ -742,17 +742,17 @@ $SLANG = array(
|
|||
'Update' => 'Aggiorna',
|
||||
'UpdateAvailable' => 'Un aggiornamento di ZoneMinder è disponibilie.',
|
||||
'UpdateNotNecessary' => 'Nessun aggiornamento necessario.',
|
||||
'Updated' => 'Updated', // Added - 2011-06-16
|
||||
'Upload' => 'Upload', // Added - 2011-08-23
|
||||
'Updated' => 'Aggiornato', // Added - 2011-06-16
|
||||
'Upload' => 'Carica', // Added - 2011-08-23
|
||||
'UseFilter' => 'Usa Filtro',
|
||||
'UseFilterExprsPost' => ' espressioni filtri', // This is used at the end of the phrase 'use N filter expressions'
|
||||
'UseFilterExprsPost' => ' espressioni filtri', // This is used at the end of the phrase 'use N filter expressions'
|
||||
'UseFilterExprsPre' => 'Usa ', // This is used at the beginning of the phrase 'use N filter expressions'
|
||||
'UsedPlugins' => 'Used Plugins',
|
||||
'UsedPlugins' => 'Plugins in uso',
|
||||
'User' => 'Utente',
|
||||
'Username' => 'Nome Utente',
|
||||
'Users' => 'Utenti',
|
||||
'V4L' => 'V4L', // Added - 2015-04-18
|
||||
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
|
||||
'V4LCapturesPerFrame' => 'Rilevamenti per immagine', // Added - 2015-04-18
|
||||
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
|
||||
'Value' => 'Valore',
|
||||
'Version' => 'Versione',
|
||||
|
@ -767,9 +767,9 @@ $SLANG = array(
|
|||
'VideoGenFiles' => 'File Video Esistenti',
|
||||
'VideoGenNoFiles' => 'Non ho trovato file ',
|
||||
'VideoGenParms' => 'Parametri Generazione Video',
|
||||
'VideoGenSucceeded' => 'Successo: Generato Video !',
|
||||
'VideoGenSucceeded' => 'Successo: Video Generato!',
|
||||
'VideoSize' => 'Dimensioni Video',
|
||||
'VideoWriter' => 'Scrittore video', // Added - 2018-08-30
|
||||
'VideoWriter' => 'Scrittore Video', // Added - 2018-08-30
|
||||
'View' => 'Vedi',
|
||||
'ViewAll' => 'Vedi Tutto',
|
||||
'ViewEvent' => 'Vedi Evento',
|
||||
|
@ -782,20 +782,20 @@ $SLANG = array(
|
|||
'WebSiteUrl' => 'Website URL', // Added - 2018-08-30
|
||||
'Week' => 'Settimana',
|
||||
'White' => 'Bianco',
|
||||
'WhiteBalance' => 'Bil. Bianco ',
|
||||
'WhiteBalance' => 'Bilanciamento del Bianco',
|
||||
'Wide' => 'Larghezza',
|
||||
'X' => 'X',
|
||||
'X10' => 'X10',
|
||||
'X10ActivationString' => 'Stringa attivazione X10',
|
||||
'X10InputAlarmString' => 'Stringa allarme input X10',
|
||||
'X10OutputAlarmString' => 'Stringa allarme output X10',
|
||||
'Y' => 'Y',
|
||||
'Y' => 'S',
|
||||
'Yes' => 'Si',
|
||||
'YouNoPerms' => 'Non hai i permessi per accedere a questa risorsa.',
|
||||
'Zone' => 'Zona',
|
||||
'ZoneAlarmColour' => 'Colore Allarme (RGB)',
|
||||
'ZoneArea' => 'Zone Area',
|
||||
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
|
||||
'ZoneExtendAlarmFrames' => 'Estendi conteggio immagini allarme',
|
||||
'ZoneFilterSize' => 'Larghezza/Altezza Filtro (pixels)',
|
||||
'ZoneMinMaxAlarmArea' => 'Min/Max Area Allarmata',
|
||||
'ZoneMinMaxBlobArea' => 'Min/Max Area di Blob',
|
||||
|
@ -803,7 +803,7 @@ $SLANG = array(
|
|||
'ZoneMinMaxFiltArea' => 'Min/Max Area Filtrata',
|
||||
'ZoneMinMaxPixelThres' => 'Min/Max Soglia Pixel (0-255)',
|
||||
'ZoneMinderLog' => 'ZoneMinder Log', // Added - 2011-06-17
|
||||
'ZoneOverloadFrames' => 'Overload Frame Ignore Count',
|
||||
'ZoneOverloadFrames' => 'Sovraccarico - contatore immagini ignorate',
|
||||
'Zones' => 'Zone',
|
||||
'Zoom' => 'Zoom',
|
||||
'ZoomIn' => 'Ingrandisci',
|
||||
|
|
|
@ -746,3 +746,9 @@ a.flip {
|
|||
#modalLogout .modal-body {
|
||||
overflow:auto;
|
||||
}
|
||||
#shutdownButton {
|
||||
padding: 3px 10px 5px 10px;
|
||||
color: white;
|
||||
}
|
||||
#shutdownButton i {
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ select {
|
|||
input[name="filter[EmailSubject]"],
|
||||
input[name="filter[EmailTo]"],
|
||||
textarea[name="filter[EmailBody]"] {
|
||||
width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
select#Id {
|
||||
min-width: 500px;
|
||||
|
@ -71,3 +71,16 @@ min-width: 500px;
|
|||
.Name input {
|
||||
min-width: 500px;
|
||||
}
|
||||
#ActionsAndOptions {
|
||||
padding-top: 5px;
|
||||
border-top: 1px solid #7f7fb2;
|
||||
border-bottom: 1px solid #7f7fb2;
|
||||
}
|
||||
#ActionsAndOptions:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ZoneMinder Base Stylesheet, $Date$, $Revision$
|
||||
* ZoneMinder Dark Stylesheet, $Date$, $Revision$
|
||||
* Copyright (C) 2001-2008 Philip Coombes
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -47,7 +47,7 @@ p {
|
|||
}
|
||||
|
||||
th {
|
||||
color: #117AAd;
|
||||
color: #10a4e8;
|
||||
}
|
||||
|
||||
img.normal {
|
||||
|
@ -147,9 +147,9 @@ fieldset {
|
|||
border-bottom: 1px solid #000000;
|
||||
}
|
||||
|
||||
input {
|
||||
input, textarea, select, button, .btn-primary {
|
||||
background-color: rgb(68,68,68);
|
||||
color: #999;
|
||||
color: #dddddd;
|
||||
}
|
||||
/* PP - make it easy to identify disabled buttons */
|
||||
|
||||
|
@ -185,7 +185,8 @@ input[type=submit]:disabled,
|
|||
}
|
||||
|
||||
.table-hover > tbody > tr:hover {
|
||||
background-color: orange;
|
||||
color: orange;
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover {
|
||||
|
@ -216,6 +217,14 @@ li.search-choice {
|
|||
}
|
||||
/* end chosen override */
|
||||
|
||||
modal-content {
|
||||
background-color: #222222;
|
||||
.modal-content {
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
ul.nav.nav-pills.flex-column {
|
||||
background-color: #485460;
|
||||
}
|
||||
|
||||
.thead-highlight {
|
||||
background-color:#485460;
|
||||
}
|
|
@ -225,15 +225,15 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
|
|||
<h2><?php echo translate('Images').': '.validHtmlStr($event->Name()).( (!empty($otherlinks)) ? ' ('.$otherlinks.') ' : '' ) ?></h2>
|
||||
|
||||
<?php
|
||||
if ( $event->DefaultVideo() ) {
|
||||
if ($event->DefaultVideo()) {
|
||||
// videojs zoomrotate only when direct recording
|
||||
$Zoom = 1;
|
||||
$Rotation = 0;
|
||||
$Monitor = $event->Monitor();
|
||||
if ( $Monitor->VideoWriter() == '2' ) {
|
||||
if ($Monitor->VideoWriter() == '2') {
|
||||
# Passthrough
|
||||
$Rotation = $event->Orientation();
|
||||
if ( in_array($event->Orientation(), array('ROTATE_90','ROTATE_270')) )
|
||||
if (in_array($event->Orientation(), array('ROTATE_90','ROTATE_270')))
|
||||
$Zoom = $event->Height()/$event->Width();
|
||||
} # end if passthrough
|
||||
?>
|
||||
|
@ -242,7 +242,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
|
|||
width="<?php echo $event->Width() ?>"
|
||||
height="<?php echo $event->Height() ?>"
|
||||
data-setup='{ "controls": true, "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'>
|
||||
<source src="<?php echo $event->getStreamSrc(array('mode'=>'mpeg','format'=>'h264')); ?>" type="video/mp4">
|
||||
<source src="<?php echo $event->DefaultVideo(); ?>" type="video/mp4">
|
||||
<track id="monitorCaption" kind="captions" label="English" srclang="en" src='data:plain/text;charset=utf-8,"WEBVTT\n\n 00:00:00.000 --> 00:00:01.000 ZoneMinder"' default>
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
@ -250,7 +250,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
|
|||
<?php
|
||||
} else { // end if DefaultVideo
|
||||
?>
|
||||
<ilayer id="slidensmain" width=&{slidewidth}; height=&{slideheight}; bgColor=&{slidebgcolor}; visibility=hide>
|
||||
<ilayer id="slidensmain" width="&{slidewidth};" height="&{slideheight};" bgColor="&{slidebgcolor};" visibility="hide">
|
||||
<layer id="slidenssub" width="&{slidewidth};" left="auto" top="auto"></layer>
|
||||
</ilayer>
|
||||
<div id="imagevideo" align="center"></div>
|
||||
|
@ -570,30 +570,24 @@ else if (document.layers) window.onload=start_slider;
|
|||
return ob_get_clean();
|
||||
} # end function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist)
|
||||
|
||||
function eventlist_html($Event, $exportDetail, $exportFrames) {
|
||||
$html = '<div class="event">
|
||||
';
|
||||
if ( $Event->SaveJPEGs() ) {
|
||||
function eventlist_html($Event, $exportDetail, $exportFrames, $exportStructure) {
|
||||
$html = '';
|
||||
if ($Event->SaveJPEGs()) {
|
||||
$html .= '<a href="#" onclick="switchevent(\''.$Event->Id().'/zmEventImages.html\');return false;">
|
||||
';
|
||||
if ( ZM_WEB_LIST_THUMBS ) {
|
||||
$html .= '<img width="'.ZM_WEB_LIST_THUMB_WIDTH.'" src="'. $Event->Id().'/snapshot.jpg" alt="'.$Event->Id().'"/>
|
||||
$html .= '<img width="'.ZM_WEB_LIST_THUMB_WIDTH.'" src="'. $Event->Id().($exportStructure=='flat'?'_':'/').'snapshot.jpg" alt="'.$Event->Id().'"/>
|
||||
';
|
||||
} else {
|
||||
$html .= $Event->Id();
|
||||
}
|
||||
$html .= '</a><br/>
|
||||
';
|
||||
} # end if has jpegs
|
||||
if ( $Event->DefaultVideo() ) {
|
||||
if ( ZM_WEB_LIST_THUMBS ) {
|
||||
$html .= '<a href="'.$Event->Id().'/'.$Event->DefaultVideo() .'">';
|
||||
$html .= '<img width="'.ZM_WEB_LIST_THUMB_WIDTH.'" src="'. $Event->Id().'/snapshot.jpg" alt="'.$Event->Id().'"/>';
|
||||
$html .= '</a><br/>
|
||||
';
|
||||
}
|
||||
if ($Event->DefaultVideo()) {
|
||||
$html .= '<a href="'.$Event->Id().'/'.$Event->DefaultVideo() .'">';
|
||||
$html .= '<img width="'.ZM_WEB_LIST_THUMB_WIDTH.'" src="'. $Event->Id().($exportStructure=='flat'?'_':'/').'snapshot.jpg" alt="'.$Event->Id().'"/>';
|
||||
$html .= '</a><br/>'.PHP_EOL;
|
||||
}
|
||||
if ( $exportDetail ) {
|
||||
if ($exportDetail) {
|
||||
$html .= '<a href="#" onclick="switchevent(\''.$Event->Id().'/zmEventDetail.html\');return false;">Detail</a>
|
||||
';
|
||||
}
|
||||
|
@ -601,12 +595,12 @@ function eventlist_html($Event, $exportDetail, $exportFrames) {
|
|||
$html .= '<a href="#" onclick="switchevent(\''.$Event->Id().'/zmEventFrames.html\');return false;">Frames</a>
|
||||
';
|
||||
}
|
||||
$html .= '</div><!--event-->
|
||||
';
|
||||
if (!$html) $html = $Event->Id();
|
||||
$html = '<div class="event">'.PHP_EOL.$html.PHP_EOL.'</div><!--event-->'.PHP_EOL;
|
||||
return $html;
|
||||
} // end function eventlist_html
|
||||
|
||||
function exportEventImagesMaster($eids, $exportDetail, $exportFrames) {
|
||||
function exportEventImagesMaster($eids, $exportDetail, $exportFrames, $exportStructure) {
|
||||
ob_start();
|
||||
exportHeader(translate('Images').' Master');
|
||||
?>
|
||||
|
@ -615,7 +609,7 @@ function exportEventImagesMaster($eids, $exportDetail, $exportFrames) {
|
|||
<?php
|
||||
$events = ZM\Event::find(array('Id'=>$eids));
|
||||
|
||||
foreach ( $events as $event ) {
|
||||
foreach ($events as $event) {
|
||||
//get monitor id and event id
|
||||
$eventMonitorId[$event->Id()] = $event->MonitorId();
|
||||
$eventPath[$event->Id()] = $event->Relative_Path();
|
||||
|
@ -625,7 +619,7 @@ function exportEventImagesMaster($eids, $exportDetail, $exportFrames) {
|
|||
$monitorNames = array();
|
||||
|
||||
//*
|
||||
if ( !empty($monitors) ) {
|
||||
if (!empty($monitors)) {
|
||||
$tmp = dbFetchAll('SELECT Id, Name FROM Monitors WHERE Id IN ('.implode(',', $monitors).') ');
|
||||
foreach ( $tmp as $row ) { $monitorNames[$row['Id']] = $row['Name']; }
|
||||
}
|
||||
|
@ -641,31 +635,31 @@ function exportEventImagesMaster($eids, $exportDetail, $exportFrames) {
|
|||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<table>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td valign="top" bgcolor="#dddddd" style="padding:10px;">
|
||||
<div class="tab_content" id="all">
|
||||
<h2> All </h2>
|
||||
<?php
|
||||
foreach($events as $event) {
|
||||
echo eventlist_html($event, $exportDetail, $exportFrames);
|
||||
foreach ($events as $event) {
|
||||
echo eventlist_html($event, $exportDetail, $exportFrames, $exportStructure);
|
||||
} # end foreach event
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
foreach ( $monitors as $monitor_id ) {
|
||||
foreach ($monitors as $monitor_id) {
|
||||
echo '<div class="tab_content" id="tab'.$monitor_id.'">';
|
||||
echo '<h2>Monitor: '.$monitorNames[$monitor_id].'</h2>';
|
||||
foreach ( $events as $event ) {
|
||||
if ( $event->MonitorId() == $monitor_id ) {
|
||||
echo eventlist_html($event, $exportDetail, $exportFrames);
|
||||
foreach ($events as $event) {
|
||||
if ($event->MonitorId() == $monitor_id) {
|
||||
echo eventlist_html($event, $exportDetail, $exportFrames, $exportStructure);
|
||||
} # end if its the right monitor
|
||||
} # end foreach event
|
||||
echo '</div>';
|
||||
} # end foreach monitor
|
||||
?>
|
||||
|
||||
</td><td valign="top">
|
||||
</td><td valign="top" style="height: 100%;">
|
||||
<iframe id="myframe" onload="resizeCaller();" name="myframe" src="about:blank"
|
||||
scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
|
||||
vspace="0" hspace="0" style="overflow:visible; width:100%; display:none">
|
||||
|
@ -772,53 +766,64 @@ function exportFileList(
|
|||
$exportVideo,
|
||||
$exportMisc
|
||||
) {
|
||||
|
||||
if ( !canView('Events') or !$event ) {
|
||||
if (!$event) {
|
||||
ZM\Error("Empty event passed to exportFileList");
|
||||
return;
|
||||
}
|
||||
if (!$event->canView()) {
|
||||
ZM\Error('Can\'t view event '.$event->Id());
|
||||
return;
|
||||
}
|
||||
|
||||
$eventPath = $event->Path();
|
||||
$eventRelativePath = $event->Relative_Path();
|
||||
$files = array();
|
||||
if ( $dir = opendir($eventPath) ) {
|
||||
while ( ($file = readdir($dir)) !== false ) {
|
||||
if ( is_file($eventPath.'/'.$file) ) {
|
||||
if ($dir = opendir($eventPath)) {
|
||||
while (($file = readdir($dir)) !== false) {
|
||||
if (is_file($eventPath.'/'.$file)) {
|
||||
$files[$file] = $file;
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
ZM\Debug(print_r($files, true));
|
||||
|
||||
$exportFileList = array();
|
||||
|
||||
if ( $exportDetail ) {
|
||||
if ($exportDetail) {
|
||||
$file = 'zmEventDetail.html';
|
||||
if ( $fp = fopen($eventPath.'/'.$file, 'w') ) {
|
||||
if ($fp = fopen($eventPath.'/'.$file, 'w')) {
|
||||
fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
|
||||
fclose($fp);
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
ZM\Error("Can't open event detail export file '$file'");
|
||||
ZM\Error("Can't open event detail export file '$eventPath/$file'");
|
||||
}
|
||||
} else {
|
||||
ZM\Debug('Not including detail');
|
||||
}
|
||||
|
||||
if ( $exportFrames ) {
|
||||
if ($exportFrames) {
|
||||
$file = 'zmEventFrames.html';
|
||||
if ( $fp = fopen($eventPath.'/'.$file, 'w') ) {
|
||||
if ($fp = fopen($eventPath.'/'.$file, 'w')) {
|
||||
fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
|
||||
fclose($fp);
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
ZM\Error("Can't open event frames export file '$file'");
|
||||
ZM\Error("Can't open event frames export file '$eventPath/$file' is writable? ".is_writable($eventPath));
|
||||
}
|
||||
} else {
|
||||
ZM\Debug('Not including frames');
|
||||
}
|
||||
|
||||
if ( $exportImages ) {
|
||||
if ($exportImages) {
|
||||
$filesLeft = array();
|
||||
$myfilelist = array();
|
||||
foreach ( $files as $file ) {
|
||||
if ( preg_match('/-(?:capture|analyse).jpg$/', $file) ) {
|
||||
foreach ($files as $file) {
|
||||
if (preg_match('/-(?:capture|analyse).jpg$/', $file)) {
|
||||
$myfilelist[$file] = $exportFileList[$file] = $file;
|
||||
} else if ($exportVideo and preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file)) {
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
$filesLeft[$file] = $file;
|
||||
}
|
||||
|
@ -826,36 +831,27 @@ function exportFileList(
|
|||
$files = $filesLeft;
|
||||
|
||||
// create an image slider
|
||||
if ( !empty($myfilelist) ) {
|
||||
$file = 'zmEventImages.html';
|
||||
if ( $fp = fopen($eventPath.'/'.$file, 'w') ) {
|
||||
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
|
||||
fclose($fp);
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
ZM\Error("Can't open event images export file '$file'");
|
||||
}
|
||||
$file = 'zmEventImages.html';
|
||||
if ($fp = fopen($eventPath.'/'.$file, 'w')) {
|
||||
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
|
||||
fclose($fp);
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
ZM\Error("Can't open event images export file '$file'");
|
||||
}
|
||||
} else {
|
||||
ZM\Debug('Not including frame images');
|
||||
} # end if exportImages
|
||||
|
||||
if ( $exportVideo ) {
|
||||
$filesLeft = array();
|
||||
foreach ( $files as $file ) {
|
||||
if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
$filesLeft[$file] = $file;
|
||||
}
|
||||
}
|
||||
$files = $filesLeft;
|
||||
} # end if exportVideo
|
||||
|
||||
if ( $exportMisc ) {
|
||||
foreach ( $files as $file ) {
|
||||
if ($exportMisc) {
|
||||
foreach ($files as $file) {
|
||||
$exportFileList[$file] = $file;
|
||||
}
|
||||
$files = array();
|
||||
} else {
|
||||
ZM\Debug('Not including misc');
|
||||
}
|
||||
ZM\Debug(print_r($exportFileList, true));
|
||||
return array_values($exportFileList);
|
||||
} # end exportFileList()
|
||||
|
||||
|
@ -869,76 +865,89 @@ function exportEvents(
|
|||
$exportMisc,
|
||||
$exportFormat,
|
||||
$exportCompressed,
|
||||
$exportStructure = false
|
||||
$exportStructure = false,
|
||||
$export_root = 'zmExport'
|
||||
) {
|
||||
|
||||
if ( !canView('Events') ) {
|
||||
if (!(canView('Events') or canView('Snapshots'))) {
|
||||
ZM\Error('You do not have permission to view events.');
|
||||
return false;
|
||||
} else if ( empty($eids) ) {
|
||||
} else if (empty($eids)) {
|
||||
ZM\Error('Attempt to export an empty list of events.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !($exportFormat == 'tar' or $exportFormat == 'zip') ) {
|
||||
if (!($exportFormat == 'tar' or $exportFormat == 'zip')) {
|
||||
ZM\Error("None or invalid exportFormat specified $exportFormat.");
|
||||
return false;
|
||||
}
|
||||
|
||||
# Ensure that we are going to be able to do this.
|
||||
if ( ! ( mkdir(ZM_DIR_EXPORTS) or file_exists(ZM_DIR_EXPORTS) ) ) {
|
||||
if (!(@mkdir(ZM_DIR_EXPORTS) or file_exists(ZM_DIR_EXPORTS))) {
|
||||
ZM\Fatal('Can\'t create exports dir at \''.ZM_DIR_EXPORTS.'\'');
|
||||
}
|
||||
chmod(ZM_DIR_EXPORTS, 0700);
|
||||
$export_dir = ZM_DIR_EXPORTS.'/zmExport_'.$connkey;
|
||||
$export_dir = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'');
|
||||
|
||||
# Ensure that we are going to be able to do this.
|
||||
if ( ! ( mkdir($export_dir) or file_exists($export_dir) ) ) {
|
||||
if (!(@mkdir($export_dir) or file_exists($export_dir))) {
|
||||
ZM\Error("Can't create exports dir at '$export_dir'");
|
||||
return false;
|
||||
}
|
||||
ZM\Debug("Successfully created dir '$export_dir'");
|
||||
chmod($export_dir, 0700);
|
||||
if ( !chdir($export_dir) ) {
|
||||
if (!chdir($export_dir)) {
|
||||
ZM\Error("Can't chdir to $export_dir");
|
||||
return;
|
||||
}
|
||||
|
||||
$export_root = 'zmExport';
|
||||
$export_listFile = 'zmFileList.txt';
|
||||
$exportFileList = array();
|
||||
$html_eventMaster = '';
|
||||
|
||||
if ( !is_array($eids) ) {
|
||||
if (!is_array($eids)) {
|
||||
$eids = array($eids);
|
||||
}
|
||||
foreach ( $eids as $eid ) {
|
||||
foreach ($eids as $eid) {
|
||||
$event = new ZM\Event($eid);
|
||||
if (!$event->canView()) {
|
||||
global $user;
|
||||
ZM\Warning('User '.($user?$user['Username']:'').' cannot view event '.$event->Id());
|
||||
continue;
|
||||
}
|
||||
$event_dir = $export_dir.'/'.$event->Id();
|
||||
if ( !(mkdir($event_dir) or file_exists($event_dir)) ) {
|
||||
if (!(@mkdir($event_dir) or file_exists($event_dir))) {
|
||||
ZM\Error("Can't mkdir $event_dir");
|
||||
}
|
||||
$event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc);
|
||||
$exportFileList = array_merge($exportFileList, $event_exportFileList);
|
||||
foreach ( $event_exportFileList as $file ) {
|
||||
foreach ($event_exportFileList as $file) {
|
||||
#if ( preg_match('/\.html$/', $file) )
|
||||
#continue;
|
||||
$cmd = 'cp -as '.$event->Path().'/'.$file.' '.$export_dir.'/'.$event->Id().'/'.$file. ' 2>&1';
|
||||
if ($exportStructure == 'flat') {
|
||||
$cmd = 'cp -as '.$event->Path().'/'.$file.' '.$export_dir.'/'.$event->Id().'_'.$file. ' 2>&1';
|
||||
} else {
|
||||
$cmd = 'cp -as '.$event->Path().'/'.$file.' '.$export_dir.'/'.$event->Id().'/'.$file. ' 2>&1';
|
||||
}
|
||||
exec($cmd, $output, $return);
|
||||
ZM\Debug($cmd.' return code: '.$return.' output: '.print_r($output,true));
|
||||
} # end foreach event_exportFile
|
||||
} # end foreach event
|
||||
|
||||
if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.min.js', $export_dir.'/jquery.min.js') )
|
||||
ZM\Error('Failed linking jquery.min.js');
|
||||
if (!(
|
||||
@symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.min.js', $export_dir.'/jquery.min.js')
|
||||
or
|
||||
file_exists($export_dir.'/jquery.min.js')
|
||||
)) {
|
||||
ZM\Error('Failed linking '.ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.min.js to '.$export_dir.'/jquery.min.js');
|
||||
}
|
||||
//if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/video.js', $export_dir.'/video.js') )
|
||||
//Error("Failed linking video.js");
|
||||
|
||||
$html_eventMaster_file = 'zmEventImagesMaster.html';
|
||||
$html_eventMaster_path = $export_dir.'/'.$html_eventMaster_file;
|
||||
|
||||
if ( ($fp = fopen($html_eventMaster_path, 'w')) ) {
|
||||
fwrite($fp, exportEventImagesMaster($eids, $exportDetail, $exportFrames));
|
||||
if (($fp = fopen($html_eventMaster_path, 'w'))) {
|
||||
fwrite($fp, exportEventImagesMaster($eids, $exportDetail, $exportFrames, $exportStructure));
|
||||
fclose($fp);
|
||||
$exportFileList[] = $html_eventMaster_file;
|
||||
} else {
|
||||
|
@ -946,58 +955,63 @@ function exportEvents(
|
|||
}
|
||||
|
||||
$listFile = $export_dir.'/'.$export_listFile;
|
||||
if ( !($fp = fopen($listFile, 'w')) ) {
|
||||
ZM\Fatal("Can't open event export list file '$listFile'");
|
||||
if (!($fp = fopen($listFile, 'w'))) {
|
||||
ZM\Error("Can't open event export list file '$listFile'");
|
||||
return false;
|
||||
}
|
||||
foreach ( $exportFileList as $exportFile ) {
|
||||
$exportFile = 'zmExport'.$connkey.'/'.$exportFile;
|
||||
fwrite($fp, "$exportFile\n");
|
||||
foreach ($exportFileList as $exportFile) {
|
||||
$exportFile = $export_root.$connkey.'/'.$exportFile;
|
||||
fwrite($fp, $exportFile.PHP_EOL);
|
||||
}
|
||||
fwrite($fp, "$listFile\n");
|
||||
fwrite($fp, $listFile.PHP_EOL);
|
||||
fclose($fp);
|
||||
|
||||
chdir(ZM_DIR_EXPORTS);
|
||||
$archive = '';
|
||||
if ( $exportFormat == 'tar' ) {
|
||||
$archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.tar';
|
||||
$version = shell_exec('tar -v');
|
||||
if ($exportFormat == 'tar') {
|
||||
$archive = $export_root.($connkey?'_'.$connkey:'').'.tar';
|
||||
$version = @shell_exec('tar --version');
|
||||
ZM\Debug("Version $version");
|
||||
|
||||
$command = 'tar --create --dereference';
|
||||
if ( $exportCompressed ) {
|
||||
if ($exportCompressed) {
|
||||
$archive .= '.gz';
|
||||
$command .= ' --gzip';
|
||||
$exportFormat .= '.gz';
|
||||
}
|
||||
if ( $exportStructure == 'flat' ) {
|
||||
if ( preg_match('/BSD/i', $version) ) {
|
||||
if ($exportStructure == 'flat') {
|
||||
if (preg_match('/BSD/i', $version)) {
|
||||
$command .= ' -s \'#^.*/##\'';
|
||||
} else {
|
||||
$command .= ' --xform=\'s#^.+/##x\'';
|
||||
}
|
||||
}
|
||||
$command .= ' --file='.escapeshellarg($archive);
|
||||
} elseif ( $exportFormat == 'zip' ) {
|
||||
$archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.zip';
|
||||
$command = 'zip ';
|
||||
$command .= ($exportStructure == 'flat' ? ' -j ' : ' -r ' ).escapeshellarg($archive);
|
||||
$archive_path = ZM_DIR_EXPORTS.'/'.$archive;
|
||||
$command .= ' --file='.escapeshellarg($archive_path);
|
||||
} else if ($exportFormat == 'zip') {
|
||||
$archive = $export_root.($connkey?'_'.$connkey:'').'.zip';
|
||||
$archive_path = ZM_DIR_EXPORTS.'/'.$archive;
|
||||
$command = 'zip -r ';
|
||||
$command .= ($exportStructure == 'flat' ? ' -j ' : '').escapeshellarg($archive_path);
|
||||
$command .= $exportCompressed ? ' -9' : ' -0';
|
||||
} // if $exportFormat
|
||||
|
||||
@unlink($archive);
|
||||
$command .= ' zmExport_' . $connkey.'/';
|
||||
@unlink($archive_path);
|
||||
$command .= ' '.$export_root.($connkey?'_'.$connkey:'').'/';
|
||||
ZM\Debug($command);
|
||||
exec($command, $output, $status);
|
||||
if ( $status ) {
|
||||
if ($status) {
|
||||
ZM\Error("Command '$command' returned with status $status");
|
||||
if ( isset($output[0]) ) {
|
||||
if (isset($output[0])) {
|
||||
ZM\Error('First line of output is \''.$output[0].'\'');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// clean up temporary files
|
||||
if ( !empty($html_eventMaster) ) {
|
||||
if (!empty($html_eventMaster)) {
|
||||
unlink($monitorPath.'/'.$html_eventMaster);
|
||||
}
|
||||
|
||||
return '?view=archive&type='.$exportFormat.'&connkey='.$connkey;
|
||||
return '?view=archive&type='.$exportFormat.'&connkey='.$connkey.'&file='.$archive;
|
||||
} // end function exportEvents
|
||||
|
|
|
@ -766,25 +766,23 @@ function getAccountCircleHTML($skin, $user=null) {
|
|||
function getStatusBtnHTML($status) {
|
||||
$result = '';
|
||||
|
||||
if ( canEdit('System') ) {
|
||||
//$result .= '<li class="nav-item dropdown">'.PHP_EOL;
|
||||
if (canEdit('System')) {
|
||||
$result .= '<li id="getStatusBtnHTML">'.PHP_EOL;
|
||||
$result .= '<button type="button" class="btn btn-default navbar-btn" id="stateModalBtn">' .$status. '</button>'.PHP_EOL;
|
||||
$result .= '</li>'.PHP_EOL;
|
||||
//$result .= '</li>'.PHP_EOL;
|
||||
|
||||
if ( ZM_SYSTEM_SHUTDOWN ) {
|
||||
$result .= '<li class="navbar-text pr-2 align-self-center">'.PHP_EOL;
|
||||
$result .= '<button class="btn btn-outline" data-on-click="getShutdownModal" data-toggle="tooltip" data-placement="top" title="' .translate("Shutdown"). '" ><i class="material-icons md-18">power_settings_new</i></button>'.PHP_EOL;
|
||||
if (ZM_SYSTEM_SHUTDOWN) {
|
||||
$result .= '<li class="pr-2">'.PHP_EOL;
|
||||
$result .= '<button id="shutdownButton" class="btn btn-default navbar-btn" data-on-click="getShutdownModal" data-toggle="tooltip" data-placement="top" title="' .translate('Shutdown'). '"><i class="material-icons md-18">power_settings_new</i></button>'.PHP_EOL;
|
||||
$result .= '</li>'.PHP_EOL;
|
||||
}
|
||||
|
||||
} else if ( canView('System') ) {
|
||||
} else if (canView('System')) {
|
||||
$result .= '<li id="getStatusBtnHTML" class="navbar-text">'.PHP_EOL;
|
||||
$result .= $status.PHP_EOL;
|
||||
$result .= '</li>'.PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -900,7 +898,6 @@ function xhtmlFooter() {
|
|||
'js/Server.js',
|
||||
), true );
|
||||
?>
|
||||
<script nonce="<?php echo $cspNonce; ?>">var $j = jQuery.noConflict();</script>
|
||||
<?php
|
||||
if ( $view == 'event' ) {
|
||||
?>
|
||||
|
@ -914,7 +911,7 @@ function xhtmlFooter() {
|
|||
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
|
||||
<?php
|
||||
?>
|
||||
<script nonce="<?php echo $cspNonce; ?>">
|
||||
<script nonce="<?php echo $cspNonce; ?>">var $j = jQuery.noConflict();
|
||||
<?php
|
||||
if ( $skinJsPhpFile ) {
|
||||
require_once( $skinJsPhpFile );
|
||||
|
|
|
@ -781,7 +781,7 @@ function logAjaxFail(jqxhr, textStatus, error) {
|
|||
}
|
||||
|
||||
// Load the Modal HTML via Ajax call
|
||||
function getModal(id, parameters) {
|
||||
function getModal(id, parameters, buttonconfig=null) {
|
||||
$j.getJSON(thisUrl + '?request=modal&modal='+id+'&'+parameters)
|
||||
.done(function(data) {
|
||||
if ( !data ) {
|
||||
|
@ -790,7 +790,7 @@ function getModal(id, parameters) {
|
|||
}
|
||||
|
||||
insertModalHtml(id, data.html);
|
||||
manageModalBtns(id);
|
||||
buttonconfig ? buttonconfig() : manageModalBtns(id);
|
||||
modal = $j('#'+id+'Modal');
|
||||
if ( ! modal.length ) {
|
||||
console.log('No modal found');
|
||||
|
@ -800,6 +800,14 @@ function getModal(id, parameters) {
|
|||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function showModal(id, buttonconfig=null) {
|
||||
var div = $j('#'+id+'Modal');
|
||||
if ( ! div.length ) {
|
||||
getModal(id, buttonconfig);
|
||||
}
|
||||
div.modal('show');
|
||||
}
|
||||
|
||||
function manageModalBtns(id) {
|
||||
// Manage the CANCEL modal button, note data-dismiss="modal" would work better
|
||||
var cancelBtn = document.getElementById(id+"CancelBtn");
|
||||
|
|
|
@ -291,8 +291,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
<td class="colId"><a <?php echo ($stream_available ? 'href="?view=watch&mid='.$monitor['Id'].'">' : '>') . $monitor['Id'] ?></a></td>
|
||||
<?php
|
||||
}
|
||||
$imgHTML='';
|
||||
if (ZM_WEB_LIST_THUMBS && ($monitor['Status'] == 'Connected') && $running && canView('Stream')) {
|
||||
$imgHTML = '';
|
||||
if (ZM_WEB_LIST_THUMBS && $monitor['Function'] != 'None' && ($monitor['Status'] == 'Connected') && $running && canView('Stream')) {
|
||||
$options = array();
|
||||
|
||||
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
||||
|
|
|
@ -195,7 +195,7 @@ if ( $Event->Id() and !file_exists($Event->Path()) )
|
|||
if ( $video_tag ) {
|
||||
?>
|
||||
<div id="videoFeed">
|
||||
<video id="videoobj" class="video-js vjs-default-skin"
|
||||
<video autoplay id="videoobj" class="video-js vjs-default-skin"
|
||||
style="transform: matrix(1, 0, 0, 1, 0, 0);"
|
||||
<?php echo $scale ? 'width="'.reScale($Event->Width(), $scale).'"' : '' ?>
|
||||
<?php echo $scale ? 'height="'.reScale($Event->Height(), $scale).'"' : '' ?>
|
||||
|
|
|
@ -195,7 +195,7 @@ echo $navbar = getNavBarHTML();
|
|||
<form name="selectForm" id="selectForm" method="get" action="?">
|
||||
<input type="hidden" name="view" value="filter"/>
|
||||
<hr/>
|
||||
<div id="filterSelector"><label for="<?php echo 'Id' ?>"><?php echo translate('UseFilter') ?></label>
|
||||
<div id="filterSelector"><label for="Id"><?php echo translate('UseFilter') ?></label>
|
||||
<?php
|
||||
if ( count($filterNames) > 1 ) {
|
||||
echo htmlSelect('Id', $filterNames, $filter->Id(), array('data-on-change-this'=>'selectFilter'));
|
||||
|
@ -210,8 +210,7 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )
|
|||
?>
|
||||
</div>
|
||||
</form>
|
||||
<form name="contentForm" id="contentForm" method="post" class="validateFormOnSubmit" action="?view=filter">
|
||||
<input type="hidden" name="Id" value="<?php echo $filter->Id() ?>"/>
|
||||
<form name="contentForm" id="contentForm" method="post" class="validateFormOnSubmit" action="?view=filter&Id=<?php echo $filter->Id() ?>">
|
||||
<input type="hidden" name="action"/>
|
||||
<input type="hidden" name="object" value="filter"/>
|
||||
|
||||
|
@ -397,7 +396,7 @@ echo htmlSelect( 'filter[Query][sort_asc]', $sort_dirns, $filter->sort_asc() );
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr/>
|
||||
<div id="ActionsAndOptions">
|
||||
<div id="actionsTable" class="filterTable">
|
||||
<fieldset><legend><?php echo translate('Actions') ?></legend>
|
||||
<p>
|
||||
|
@ -502,17 +501,17 @@ if ( ZM_OPT_EMAIL ) {
|
|||
?>
|
||||
</fieldset>
|
||||
</div>
|
||||
<hr/>
|
||||
</div><!--ActionsAndOptions-->
|
||||
<div id="contentButtons">
|
||||
<button type="button" data-on-click-this="submitToEvents"><?php echo translate('ListMatches') ?></button>
|
||||
<button type="button" data-on-click-this="submitToMontageReview"><?php echo translate('ViewMatches') ?></button>
|
||||
<button type="button" data-on-click-this="submitToExport"><?php echo translate('ExportMatches') ?></button>
|
||||
<button type="button" name="executeButton" id="executeButton" data-on-click-this="executeFilter"><?php echo translate('Execute') ?></button>
|
||||
<button type="submit" name="action" value="execute" id="executeButton"><?php echo translate('Execute') ?></button>
|
||||
<?php
|
||||
if ( canEdit('Events') ) {
|
||||
?>
|
||||
<button type="submit" name="Save" value="Save" data-on-click-this="saveFilter"><?php echo translate('Save') ?></button>
|
||||
<button type="submit" name="SaveAs" value="SaveAs" data-on-click-this="saveFilter"><?php echo translate('SaveAs') ?></button>
|
||||
<button type="submit" name="action" value="Save" id="Save"><?php echo translate('Save') ?></button>
|
||||
<button type="submit" name="action" value="SaveAs" id="SaveAs"><?php echo translate('SaveAs') ?></button>
|
||||
<?php
|
||||
if ( $filter->Id() ) {
|
||||
?>
|
||||
|
|
|
@ -34,54 +34,53 @@ function startDownload(file) {
|
|||
}
|
||||
|
||||
function exportProgress() {
|
||||
if ( exportTimer ) {
|
||||
if (exportTimer) {
|
||||
var tickerText = $j('#exportProgressTicker').text();
|
||||
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
||||
$j('#exportProgressTicker').text('.');
|
||||
} else {
|
||||
$j('#exportProgressTicker').append('.');
|
||||
}
|
||||
} else {
|
||||
console.log("No timer");
|
||||
}
|
||||
}
|
||||
|
||||
function exportResponse(respObj, respText) {
|
||||
clearInterval(exportTimer);
|
||||
if ( respObj.result != 'Ok' ) {
|
||||
if (respObj.result != 'Ok') {
|
||||
$j('#exportProgressTicker').text(respObj.message);
|
||||
} else {
|
||||
$j('#exportProgressTicker').text(exportSucceededString);
|
||||
setTimeout(startDownload, 1500, decodeURIComponent(respObj.exportFile));
|
||||
}
|
||||
return;
|
||||
|
||||
if ( 0 ) {
|
||||
var eids = new Array();
|
||||
for (var i = 0, len=form.elements.length; i < len; i++) {
|
||||
if ( form.elements[i].name == 'eids[]' ) {
|
||||
eids[eids.length] = 'eids[]='+form.elements[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
form.submit();
|
||||
|
||||
//window.location.replace( thisUrl+'?view='+currentView+'&'+eids.join('&')+'&exportFile='+respObj.exportFile+'&generated='+((respObj.result=='Ok')?1:0) );
|
||||
}
|
||||
|
||||
function exportEvents( ) {
|
||||
var formData = $j('#contentForm').serialize();
|
||||
|
||||
$j.ajaxSetup({
|
||||
timeout: 0
|
||||
});
|
||||
$j.getJSON(thisUrl + '?view=event&request=event&action=export', formData)
|
||||
.done(exportResponse)
|
||||
.fail(logAjaxFail);
|
||||
.fail(exportFail);
|
||||
|
||||
$j('#exportProgress').removeClass('hidden');
|
||||
$j('#exportProgress').addClass('warnText');
|
||||
$j('#exportProgress').text(exportProgressString);
|
||||
$j('#exportProgressText').text(exportProgressString);
|
||||
|
||||
//exportProgress();
|
||||
exportTimer = setInterval(exportProgress, 500);
|
||||
}
|
||||
|
||||
function exportFail() {
|
||||
clearInterval(exportTimer);
|
||||
$j('#exportProgress').addClass('errorText');
|
||||
$j('#exportProgressTicker').text('Failed export');
|
||||
logAjaxFail();
|
||||
}
|
||||
|
||||
function getEventDetailModal(eid) {
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=eventdetail&eids[]=' + eid)
|
||||
.done(function(data) {
|
||||
|
|
|
@ -57,8 +57,8 @@ function validateForm(form) {
|
|||
form.elements['filter[AutoUnarchive]'].checked ||
|
||||
form.elements['filter[UpdateDiskSpace]'].checked ||
|
||||
form.elements['filter[AutoVideo]'].checked ||
|
||||
form.elements['filter[AutoEmail]'].checked ||
|
||||
form.elements['filter[AutoMessage]'].checked ||
|
||||
(form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked) ||
|
||||
(form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked) ||
|
||||
form.elements['filter[AutoExecute]'].checked ||
|
||||
form.elements['filter[AutoDelete]'].checked ||
|
||||
form.elements['filter[AutoCopy]'].checked ||
|
||||
|
@ -97,13 +97,13 @@ function updateButtons(element) {
|
|||
} else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
|
||||
canExecute = true;
|
||||
}
|
||||
form.elements['executeButton'].disabled = !canExecute;
|
||||
document.getElementById('executeButton').disabled = !canExecute;
|
||||
if ( form.elements['filter[Name]'].value ) {
|
||||
form.elements['Save'].disabled = false;
|
||||
form.elements['SaveAs'].disabled = false;
|
||||
document.getElementById('Save').disabled = false;
|
||||
document.getElementById('SaveAs').disabled = false;
|
||||
} else {
|
||||
form.elements['Save'].disabled = true;
|
||||
form.elements['SaveAs'].disabled = true;
|
||||
document.getElementById('Save').disabled = true;
|
||||
document.getElementById('SaveAs').disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,11 +151,6 @@ function resetFilter( element ) {
|
|||
|
||||
function submitToEvents(element) {
|
||||
var form = element.form;
|
||||
//form.action = '?view=events';
|
||||
//form.submit();
|
||||
//console.log(form);
|
||||
//console.log($j(form).serialize());
|
||||
//history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
||||
window.location.assign('?view=events&'+$j(form).serialize());
|
||||
}
|
||||
|
||||
|
@ -171,23 +166,6 @@ function submitToExport(element) {
|
|||
window.location.assign('?view=export&'+$j(form).serialize());
|
||||
}
|
||||
|
||||
function executeFilter( element ) {
|
||||
var form = element.form;
|
||||
form.action = thisUrl + '?view=filter';
|
||||
form.elements['action'].value = 'execute';
|
||||
form.submit();
|
||||
//history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
||||
}
|
||||
|
||||
function saveFilter( element ) {
|
||||
var form = element.form;
|
||||
form.target = window.name;
|
||||
form.elements['action'].value = element.value;
|
||||
form.action = thisUrl + '?view=filter';
|
||||
//form.submit();
|
||||
// Submit is done by the button type="submit"
|
||||
}
|
||||
|
||||
function deleteFilter( element ) {
|
||||
var form = element.form;
|
||||
if ( confirm( deleteSavedFilterString+" '"+form.elements['filter[Name]'].value+"'?" ) ) {
|
||||
|
@ -350,7 +328,8 @@ function parseRows(rows) {
|
|||
inputTds.eq(2).children().eq(0).attr('name', 'filter'+stringFilter(term));
|
||||
inputTds.eq(2).children().eq(0).attr('id', 'filter'+stringFilter(term));
|
||||
} //End for each term/row
|
||||
history.replaceState(null, null, '?view=filter&' + $j('#contentForm').serialize());
|
||||
// ICON This populates the url bar with contents of the form. I'm not sure why
|
||||
// history.replaceState(null, null, '?view=filter&' + $j('#contentForm').serialize());
|
||||
} // parseRows
|
||||
|
||||
function stringFilter(term) {
|
||||
|
@ -415,4 +394,4 @@ function initPage() {
|
|||
parseRows($j('#fieldsTable tbody').children());
|
||||
}
|
||||
|
||||
$j(document).ready(initPage );
|
||||
$j(document).ready(initPage);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
function submitCamera( element ) {
|
||||
var form = element.form;
|
||||
form.target = opener.name;
|
||||
if (opener) {
|
||||
form.target = opener.name;
|
||||
}
|
||||
form.view.value = 'monitor';
|
||||
form.submit();
|
||||
}
|
||||
|
|
|
@ -7,23 +7,23 @@ function selectLayout(element) {
|
|||
var ddm = $j('#zmMontageLayout');
|
||||
layout = ddm.val();
|
||||
|
||||
if ( layout_id = parseInt(layout) ) {
|
||||
if (layout_id = parseInt(layout)) {
|
||||
layout = layouts[layout];
|
||||
|
||||
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
||||
for (var i = 0, length = monitors.length; i < length; i++) {
|
||||
monitor = monitors[i];
|
||||
// Need to clear the current positioning, and apply the new
|
||||
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
if ( !monitor_frame ) {
|
||||
if (!monitor_frame) {
|
||||
console.log('Error finding frame for ' + monitor.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply default layout options, like float left
|
||||
if ( layout.Positions['default'] ) {
|
||||
if (layout.Positions['default'] ) {
|
||||
styles = layout.Positions['default'];
|
||||
for ( style in styles ) {
|
||||
for (style in styles) {
|
||||
console.log("Applying " + style + ' ' + styles[style]);
|
||||
monitor_frame.css(style, styles[style]);
|
||||
}
|
||||
|
@ -31,61 +31,72 @@ function selectLayout(element) {
|
|||
console.log("No default styles to apply" + layout.Positions);
|
||||
} // end if default styles
|
||||
|
||||
if ( layout.Positions['mId'+monitor.id] ) {
|
||||
if (layout.Positions['mId'+monitor.id]) {
|
||||
styles = layout.Positions['mId'+monitor.id];
|
||||
for ( style in styles ) {
|
||||
for (style in styles) {
|
||||
monitor_frame.css(style, styles[style]);
|
||||
}
|
||||
} else {
|
||||
console.log("No Monitor styles to apply");
|
||||
} // end if specific monitor style
|
||||
} // end foreach monitor
|
||||
setCookie('zmMontageLayout', layout_id, 3600);
|
||||
if (layouts[layout_id].Name != 'Freeform') { // 'montage_freeform.css' ) {
|
||||
// For freeform, we don't touch the width/height/scale settings, but we may need to update sizing and scales
|
||||
setCookie('zmMontageScale', '', 3600);
|
||||
$j('#scale').val('');
|
||||
$j('#width').val('0');
|
||||
}
|
||||
} // end if a stored layout
|
||||
if ( ! layout ) {
|
||||
if (!layout) {
|
||||
console.log('No layout?');
|
||||
return;
|
||||
}
|
||||
setCookie('zmMontageLayout', layout_id, 3600);
|
||||
if ( layouts[layout_id].Name != 'Freeform' ) { // 'montage_freeform.css' ) {
|
||||
setCookie('zmMontageScale', '', 3600);
|
||||
$j('#scale').val('');
|
||||
$j('#width').val('0');
|
||||
} else {
|
||||
// Is freeform, we don't touch the width/height/scale settings, but we may need to update sizing and scales
|
||||
}
|
||||
var width = parseInt($j('#width').val());
|
||||
var height = parseInt($j('#height').val());
|
||||
var scale = $j('#scale').val();
|
||||
|
||||
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
||||
for (var i = 0, length = monitors.length; i < length; i++) {
|
||||
var monitor = monitors[i];
|
||||
|
||||
if ( scale ) {
|
||||
var stream_scale = 0;
|
||||
if (scale) {
|
||||
stream_scale = scale;
|
||||
} else if ( width ) {
|
||||
} else if (width) {
|
||||
stream_scale = parseInt(100*width/monitor.width);
|
||||
} else if ( height ) {
|
||||
} else if (height) {
|
||||
stream_scale = parseInt(100*height/monitor.height);
|
||||
}
|
||||
var streamImg = document.getElementById('liveStream'+monitor.id);
|
||||
if ( streamImg ) {
|
||||
if ( streamImg.nodeName == 'IMG' ) {
|
||||
var src = streamImg.src;
|
||||
src = src.replace(/scale=\d*/i, 'scale='+scale);
|
||||
if ( height == '0' ) {
|
||||
streamImg.style.height = 'auto';
|
||||
}
|
||||
if ( src != streamImg.src ) {
|
||||
streamImg.src = '';
|
||||
streamImg.src = src;
|
||||
}
|
||||
} else if ( streamImg.nodeName == 'APPLET' || streamImg.nodeName == 'OBJECT' ) {
|
||||
// APPLET's and OBJECTS need to be re-initialized
|
||||
} else if (layouts[layout_id].Name != 'Freeform') {
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
console.log("Monitor frame width : " + monitor_frame.width() + " monitor Width: " + monitor.width);
|
||||
if (monitor_frame.width() < monitor.width) {
|
||||
stream_scale = parseInt(100 * monitor_frame.width() / monitor.width);
|
||||
// Round to a multiple of 5, so 53 become 50% etc
|
||||
stream_scale = Math.floor(stream_scale/5)*5;
|
||||
}
|
||||
streamImg.style.width = '100%';
|
||||
}
|
||||
setStreamScale('liveStream'+monitor.id, stream_scale, width, height);
|
||||
} // end foreach monitor
|
||||
} // end function selectLayout(element)
|
||||
|
||||
function setStreamScale(element_id, scale, width, height) {
|
||||
var streamImg = document.getElementById(element_id);
|
||||
if (streamImg) {
|
||||
if (streamImg.nodeName == 'IMG') {
|
||||
var src = streamImg.src;
|
||||
src = src.replace(/scale=\d*/i, 'scale='+scale);
|
||||
if (height == '0') {
|
||||
streamImg.style.height = 'auto';
|
||||
}
|
||||
if (src != streamImg.src) {
|
||||
streamImg.src = '';
|
||||
streamImg.src = src;
|
||||
}
|
||||
} else if (streamImg.nodeName == 'APPLET' || streamImg.nodeName == 'OBJECT') {
|
||||
// APPLET's and OBJECTS need to be re-initialized
|
||||
}
|
||||
//streamImg.style.width = '100%';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the widthControl|heightControl select elements are changed
|
||||
*/
|
||||
|
|
|
@ -275,17 +275,16 @@ function timerFire() {
|
|||
clearInterval(timerObj);
|
||||
timerObj = null;
|
||||
timerInterval = currentDisplayInterval;
|
||||
console.log("Turn off nterrupts timerInterfave" + timerInterval);
|
||||
console.log("Turn off interrupts timerInterfave" + timerInterval);
|
||||
}
|
||||
|
||||
if ( (currentSpeed > 0 || liveMode != 0) && ! timerObj ) {
|
||||
timerObj = setInterval(timerFire, timerInterval); // don't fire out of live mode if speed is zero
|
||||
}
|
||||
|
||||
if ( liveMode ) {
|
||||
console.log("liveMode");
|
||||
if (liveMode) {
|
||||
outputUpdate(currentTimeSecs); // In live mode we basically do nothing but redisplay
|
||||
} else if ( currentTimeSecs + playSecsPerInterval >= maxTimeSecs ) {
|
||||
} else if (currentTimeSecs + playSecsPerInterval >= maxTimeSecs) {
|
||||
// beyond the end just stop
|
||||
console.log("Current time " + currentTimeSecs + " + " + playSecsPerInterval + " >= " + maxTimeSecs + " so stopping");
|
||||
setSpeed(0);
|
||||
|
@ -499,8 +498,8 @@ function redrawScreen() {
|
|||
drawGraph();
|
||||
}
|
||||
|
||||
var monitors = $j('#monitors');
|
||||
if ( fitMode == 1 ) {
|
||||
var monitors = $j('#monitors');
|
||||
var fps = $j('#fps');
|
||||
var vh = window.innerHeight;
|
||||
var mh = (vh - monitors.position().top - fps.outerHeight());
|
||||
|
@ -637,7 +636,7 @@ function showSpeed(val) {
|
|||
}
|
||||
|
||||
function setSpeed(speed_index) {
|
||||
if ( liveMode == 1 ) {
|
||||
if (liveMode == 1) {
|
||||
console.log("setSpeed in liveMode?");
|
||||
return; // we shouldn't actually get here but just in case
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
var backBtn = $j('#backBtn');
|
||||
var saveBtn = $j('#saveBtn');
|
||||
var deleteBtn = $j('#deleteBtn');
|
||||
|
||||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
|
@ -26,6 +23,31 @@ function manageDelConfirmModalBtns() {
|
|||
});
|
||||
}
|
||||
|
||||
function downloadResponse(respObj, respText) {
|
||||
clearInterval(downloadTimer);
|
||||
if (respObj.result != 'Ok' ) {
|
||||
$j('#downloadProgressTicker').text(respObj.message);
|
||||
} else {
|
||||
$j('#downloadProgressTicker').text(downloadSucceededString);
|
||||
setTimeout(startDownload, 1500, decodeURIComponent(respObj.exportFile));
|
||||
}
|
||||
return;
|
||||
}
|
||||
function startDownload(file) {
|
||||
window.location.replace(file);
|
||||
}
|
||||
|
||||
function downloadProgress() {
|
||||
if (downloadTimer) {
|
||||
var tickerText = $j('#downloadProgressTicker').text();
|
||||
if (tickerText.length < 1 || tickerText.length > 4) {
|
||||
$j('#downloadProgressTicker').text('.');
|
||||
} else {
|
||||
$j('#downloadProgressTicker').append('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
// enable or disable buttons based on current selection and user rights
|
||||
/*
|
||||
|
@ -33,15 +55,9 @@ function initPage() {
|
|||
archiveBtn.prop('disabled', !(!eventData.Archived && canEdit.Events));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||
*/
|
||||
saveBtn.prop('disabled', !(canEdit.Events || (snapshot.CreatedBy == user.Id) ));
|
||||
/*
|
||||
exportBtn.prop('disabled', !canView.Events);
|
||||
downloadBtn.prop('disabled', !canView.Events);
|
||||
*/
|
||||
deleteBtn.prop('disabled', !canEdit.Events);
|
||||
|
||||
// Don't enable the back button if there is no previous zm page to go back to
|
||||
backBtn.prop('disabled', !document.referrer.length);
|
||||
$j('#backBtn').prop('disabled', !document.referrer.length);
|
||||
|
||||
// Manage the BACK button
|
||||
bindButton('#backBtn', 'click', null, function onBackClick(evt) {
|
||||
|
@ -56,6 +72,7 @@ function initPage() {
|
|||
});
|
||||
|
||||
// Manage the EDIT button
|
||||
$j('#saveBtn').prop('disabled', !(canEdit.Events || (snapshot.CreatedBy == user.Id) ));
|
||||
bindButton('#saveBtn', 'click', null, function onSaveClick(evt) {
|
||||
/*
|
||||
if ( ! canEdit.Events ) {
|
||||
|
@ -63,17 +80,44 @@ function initPage() {
|
|||
return;
|
||||
}
|
||||
*/
|
||||
console.log(evt);
|
||||
evt.target.form.submit();
|
||||
});
|
||||
|
||||
/*
|
||||
// Manage the EXPORT button
|
||||
bindButton('#exportBtn', 'click', null, function onExportClick(evt) {
|
||||
$j('#downloadBtn').prop('disabled', !canView.Snapshots);
|
||||
bindButton('#downloadBtn', 'click', null, function onDownloadClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.assign('?view=export&eids[]='+eventData.Id);
|
||||
formData = {
|
||||
eids: snapshot.EventIds,
|
||||
exportImages: 0,
|
||||
exportVideo: 0,
|
||||
exportFrames: 0,
|
||||
exportDetail: 0,
|
||||
exportMisc: 1,
|
||||
exportFormat: 'zip',
|
||||
exportCompress: 0,
|
||||
exportStructure: 'flat',
|
||||
exportFile: 'Snapshot'+snapshot.Id
|
||||
};
|
||||
$j.getJSON(thisUrl + '?view=event&request=event&action=export', formData)
|
||||
.done(downloadResponse)
|
||||
.fail(logAjaxFail);
|
||||
|
||||
$j('#downloadProgress').removeClass('hidden');
|
||||
$j('#downloadProgress').addClass('warnText');
|
||||
$j('#downloadProgress').text(downloadProgressString);
|
||||
|
||||
downloadTimer = setInterval(downloadProgress, 500);
|
||||
});
|
||||
|
||||
$j('#exportBtn').prop('disabled', !canView.Snapshots);
|
||||
bindButton('#exportBtn', 'click', null, function onExportClick(evt) {
|
||||
console.log('export clicked');
|
||||
evt.preventDefault();
|
||||
window.location.assign('?view=export&eids[]='+snapshot.EventIds.join('&eids[]='));
|
||||
});
|
||||
|
||||
/*
|
||||
// Manage the DOWNLOAD VIDEO button
|
||||
bindButton('#downloadBtn', 'click', null, function onDownloadClick(evt) {
|
||||
evt.preventDefault();
|
||||
|
@ -88,6 +132,7 @@ function initPage() {
|
|||
});
|
||||
*/
|
||||
// Manage the DELETE button
|
||||
$j('#deleteBtn').prop('disabled', !canEdit.Events);
|
||||
bindButton('#deleteBtn', 'click', null, function onDeleteClick(evt) {
|
||||
if ( !canEdit.Events ) {
|
||||
enoperm();
|
||||
|
|
|
@ -26,5 +26,9 @@ var eventDataStrings = {
|
|||
//
|
||||
var deleteString = "<?php echo validJsStr(translate('Delete')) ?>";
|
||||
var causeString = "<?php echo validJsStr(translate('AttrCause')) ?>";
|
||||
var downloadProgressString = "<?php echo validJsStr(translate('Downloading')) ?>";
|
||||
var downloadFailedString = '<?php echo translate('Download Failed') ?>';
|
||||
var downloadSucceededString = '<?php echo translate('Download Succeeded') ?>';
|
||||
|
||||
var WEB_LIST_THUMB_WIDTH = '<?php echo ZM_WEB_LIST_THUMB_WIDTH ?>';
|
||||
var WEB_LIST_THUMB_HEIGHT = '<?php echo ZM_WEB_LIST_THUMB_HEIGHT ?>';
|
||||
|
|
|
@ -90,7 +90,7 @@ function getDelConfirmModal() {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEdit.Events ) {
|
||||
if (!canEdit.Events) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ function manageDelConfirmModalBtns() {
|
|||
var selections = getIdSelections();
|
||||
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+selections.join('&eids[]='))
|
||||
$j.getJSON(thisUrl + '?request=snapshots&task=delete&ids[]='+selections.join('&ids[]='))
|
||||
.done( function(data) {
|
||||
$j('#snapshotTable').bootstrapTable('refresh');
|
||||
$j('#deleteConfirm').modal('hide');
|
||||
|
|
|
@ -73,10 +73,10 @@ function processRows(rows) {
|
|||
function showEvents() {
|
||||
$j('#ptzControls').addClass('hidden');
|
||||
$j('#events').removeClass('hidden');
|
||||
if ( $j('#eventsControl') ) {
|
||||
if ($j('#eventsControl')) {
|
||||
$j('#eventsControl').addClass('hidden');
|
||||
}
|
||||
if ( $j('#controlControl') ) {
|
||||
if ($j('#controlControl')) {
|
||||
$j('#controlControl').removeClass('hidden');
|
||||
}
|
||||
showMode = 'events';
|
||||
|
@ -85,10 +85,10 @@ function showEvents() {
|
|||
function showPtzControls() {
|
||||
$j('#events').addClass('hidden');
|
||||
$j('#ptzControls').removeClass('hidden');
|
||||
if ( $j('#eventsControl') ) {
|
||||
if ($j('#eventsControl')) {
|
||||
$j('#eventsControl').removeClass('hidden');
|
||||
}
|
||||
if ( $j('#controlControl') ) {
|
||||
if ($j('#controlControl')) {
|
||||
$j('#controlControl').addClass('hidden');
|
||||
}
|
||||
showMode = 'control';
|
||||
|
@ -102,7 +102,7 @@ function changeScale() {
|
|||
// Always turn it off, we will re-add it below. I don't know if you can add a callback multiple
|
||||
// times and what the consequences would be
|
||||
$j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active
|
||||
if ( scale == '0' || scale == 'auto' ) {
|
||||
if (scale == '0' || scale == 'auto') {
|
||||
var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus'));
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
|
@ -132,13 +132,13 @@ function setAlarmState(currentAlarmState) {
|
|||
alarmState = currentAlarmState;
|
||||
|
||||
var stateClass = '';
|
||||
if ( alarmState == STATE_ALARM ) {
|
||||
if (alarmState == STATE_ALARM) {
|
||||
stateClass = 'alarm';
|
||||
} else if ( alarmState == STATE_ALERT ) {
|
||||
} else if (alarmState == STATE_ALERT) {
|
||||
stateClass = 'alert';
|
||||
}
|
||||
$j('#stateValue').text(stateStrings[alarmState]);
|
||||
if ( stateClass ) {
|
||||
if (stateClass) {
|
||||
$j('#stateValue').addClass(stateClass);
|
||||
} else {
|
||||
$j('#stateValue').removeClass();
|
||||
|
@ -150,25 +150,25 @@ function setAlarmState(currentAlarmState) {
|
|||
var newAlarm = ( isAlarmed && !wasAlarmed );
|
||||
var oldAlarm = ( !isAlarmed && wasAlarmed );
|
||||
|
||||
if ( newAlarm ) {
|
||||
if (newAlarm) {
|
||||
table.bootstrapTable('refresh');
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
if (SOUND_ON_ALARM) {
|
||||
// Enable the alarm sound
|
||||
if ( !msieVer ) {
|
||||
if (!msieVer) {
|
||||
$j('#alarmSound').removeClass('hidden');
|
||||
} else {
|
||||
$j('#MediaPlayer').trigger('play');
|
||||
}
|
||||
}
|
||||
if ( POPUP_ON_ALARM ) {
|
||||
if (POPUP_ON_ALARM) {
|
||||
window.focus();
|
||||
}
|
||||
}
|
||||
if ( oldAlarm ) { // done with an event do a refresh
|
||||
if (oldAlarm) { // done with an event do a refresh
|
||||
table.bootstrapTable('refresh');
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
if (SOUND_ON_ALARM) {
|
||||
// Disable alarm sound
|
||||
if ( !msieVer ) {
|
||||
if (!msieVer) {
|
||||
$j('#alarmSound').addClass('hidden');
|
||||
} else {
|
||||
$j('#MediaPlayer').trigger('pause');
|
||||
|
@ -188,12 +188,12 @@ function getStreamCmdError(text, error) {
|
|||
|
||||
function getStreamCmdResponse(respObj, respText) {
|
||||
watchdogOk('stream');
|
||||
if ( streamCmdTimer ) {
|
||||
if (streamCmdTimer) {
|
||||
streamCmdTimer = clearTimeout(streamCmdTimer);
|
||||
}
|
||||
if ( respObj.result == 'Ok' ) {
|
||||
if (respObj.result == 'Ok') {
|
||||
// The get status command can get backed up, in which case we won't be able to get the semaphore and will exit.
|
||||
if ( respObj.status ) {
|
||||
if (respObj.status) {
|
||||
streamStatus = respObj.status;
|
||||
$j('#fpsValue').text(streamStatus.fps);
|
||||
$j('#capturefpsValue').text(streamStatus.capturefps);
|
||||
|
@ -203,9 +203,9 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
|
||||
$j('#levelValue').text(streamStatus.level);
|
||||
var newClass = 'ok';
|
||||
if ( streamStatus.level > 95 ) {
|
||||
if (streamStatus.level > 95) {
|
||||
newClass = 'alarm';
|
||||
} else if ( streamStatus.level > 80 ) {
|
||||
} else if (streamStatus.level > 80) {
|
||||
newClass = 'alert';
|
||||
}
|
||||
$j('#levelValue').removeClass();
|
||||
|
@ -213,30 +213,30 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
|
||||
var delayString = secsToTime(streamStatus.delay);
|
||||
|
||||
if ( streamStatus.paused == true ) {
|
||||
if (streamStatus.paused == true) {
|
||||
$j('#modeValue').text('Paused');
|
||||
$j('#rate').addClass('hidden');
|
||||
$j('#delayValue').text(delayString);
|
||||
$j('#delay').removeClass('hidden');
|
||||
$j('#level').removeClass('hidden');
|
||||
streamCmdPause(false);
|
||||
} else if ( streamStatus.delayed == true ) {
|
||||
} else if (streamStatus.delayed == true) {
|
||||
$j('#modeValue').text('Replay');
|
||||
$j('#rateValue').text(streamStatus.rate);
|
||||
$j('#rate').removeClass('hidden');
|
||||
$j('#delayValue').text(delayString);
|
||||
$j('#delay').removeClass('hidden');
|
||||
$j('#level').removeClass('hidden');
|
||||
if ( streamStatus.rate == 1 ) {
|
||||
if (streamStatus.rate == 1) {
|
||||
streamCmdPlay(false);
|
||||
} else if ( streamStatus.rate > 0 ) {
|
||||
if ( streamStatus.rate < 1 ) {
|
||||
} else if (streamStatus.rate > 0) {
|
||||
if (streamStatus.rate < 1) {
|
||||
streamCmdSlowFwd(false);
|
||||
} else {
|
||||
streamCmdFastFwd(false);
|
||||
}
|
||||
} else {
|
||||
if ( streamStatus.rate > -1 ) {
|
||||
if (streamStatus.rate > -1) {
|
||||
streamCmdSlowRev(false);
|
||||
} else {
|
||||
streamCmdFastRev(false);
|
||||
|
@ -251,17 +251,17 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
} // end if paused or delayed
|
||||
|
||||
$j('#zoomValue').text(streamStatus.zoom);
|
||||
if ( streamStatus.zoom == '1.0' ) {
|
||||
if (streamStatus.zoom == '1.0') {
|
||||
setButtonState('zoomOutBtn', 'unavail');
|
||||
} else {
|
||||
setButtonState('zoomOutBtn', 'inactive');
|
||||
}
|
||||
|
||||
if ( canEdit.Monitors ) {
|
||||
if ( streamStatus.enabled ) {
|
||||
if (canEdit.Monitors) {
|
||||
if (streamStatus.enabled) {
|
||||
enableAlmBtn.addClass('disabled');
|
||||
enableAlmBtn.prop('title', disableAlarmsStr);
|
||||
if ( streamStatus.forced ) {
|
||||
if (streamStatus.forced) {
|
||||
forceAlmBtn.addClass('disabled');
|
||||
forceAlmBtn.prop('title', cancelForcedAlarmStr);
|
||||
} else {
|
||||
|
@ -277,16 +277,18 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
enableAlmBtn.prop('disabled', false);
|
||||
} // end if canEdit.Monitors
|
||||
|
||||
if ( streamStatus.auth ) {
|
||||
if (streamStatus.auth) {
|
||||
auth_hash = streamStatus.auth;
|
||||
// Try to reload the image stream.
|
||||
var streamImg = $j('#liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
if (streamImg) {
|
||||
var oldSrc = streamImg.attr('src');
|
||||
var newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
streamImg.attr('src', newSrc);
|
||||
if (oldSrc != newSrc) {
|
||||
streamImg.attr('src', newSrc);
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
table.bootstrapTable('refresh');
|
||||
} // end if have a new auth hash
|
||||
} // end if respObj.status
|
||||
} else {
|
||||
|
@ -295,22 +297,20 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
// If it's an auth error, we should reload the whole page.
|
||||
console.log("have error");
|
||||
//window.location.reload();
|
||||
if ( 1 ) {
|
||||
var streamImg = $j('#liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
var oldSrc = streamImg.attr('src');
|
||||
var newSrc = oldSrc.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
var streamImg = $j('#liveStream'+monitorId);
|
||||
if (streamImg) {
|
||||
var oldSrc = streamImg.attr('src');
|
||||
var newSrc = oldSrc.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
|
||||
streamImg.attr('src', newSrc);
|
||||
console.log('Changing livestream src to ' + newSrc);
|
||||
} else {
|
||||
console.log('Unable to find streamImg liveStream');
|
||||
}
|
||||
streamImg.attr('src', newSrc);
|
||||
console.log('Changing livestream src to ' + newSrc);
|
||||
} else {
|
||||
console.log('Unable to find streamImg liveStream');
|
||||
}
|
||||
}
|
||||
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||
if (alarmState == STATE_ALARM || alarmState == STATE_ALERT) {
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
}
|
||||
streamCmdTimer = setTimeout(streamCmdQuery, streamCmdTimeout);
|
||||
|
@ -320,15 +320,15 @@ function streamCmdPause(action) {
|
|||
setButtonState('pauseBtn', 'active');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_PAUSE;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
@ -337,9 +337,9 @@ function streamCmdPause(action) {
|
|||
function streamCmdPlay(action) {
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'active');
|
||||
if ( streamStatus.delayed == true ) {
|
||||
if (streamStatus.delayed == true) {
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
|
@ -347,16 +347,16 @@ function streamCmdPlay(action) {
|
|||
}
|
||||
} else {
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
setButtonState('slowRevBtn', 'unavail');
|
||||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_PLAY;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
@ -374,15 +374,15 @@ function streamCmdStop(action) {
|
|||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'unavail');
|
||||
setButtonState('stopBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
setButtonState('slowRevBtn', 'unavail');
|
||||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_STOP;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
@ -394,15 +394,15 @@ function streamCmdFastFwd(action) {
|
|||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_FASTFWD;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
@ -412,20 +412,20 @@ function streamCmdSlowFwd(action) {
|
|||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'active');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_SLOWFWD;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
}
|
||||
}
|
||||
|
@ -434,20 +434,20 @@ function streamCmdSlowRev(action) {
|
|||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'active');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_SLOWREV;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
}
|
||||
}
|
||||
|
@ -456,23 +456,23 @@ function streamCmdFastRev(action) {
|
|||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
if (action) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_FASTREV;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdZoomIn( x, y ) {
|
||||
function streamCmdZoomIn(x, y) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.command = CMD_ZOOMIN;
|
||||
|
@ -481,22 +481,22 @@ function streamCmdZoomIn( x, y ) {
|
|||
|
||||
function streamCmdZoomOut() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_ZOOMOUT;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdScale( scale ) {
|
||||
function streamCmdScale(scale) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_SCALE;
|
||||
data.scale = scale;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdPan( x, y ) {
|
||||
function streamCmdPan(x, y) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.command = CMD_PAN;
|
||||
|
@ -505,18 +505,18 @@ function streamCmdPan( x, y ) {
|
|||
|
||||
function streamCmdQuery() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = CMD_QUERY;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function getStatusCmdResponse(respObj, respText) {
|
||||
watchdogOk('status');
|
||||
if ( statusCmdTimer ) {
|
||||
if (statusCmdTimer) {
|
||||
statusCmdTimer = clearTimeout(statusCmdTimer);
|
||||
}
|
||||
|
||||
if ( respObj.result == 'Ok' ) {
|
||||
if (respObj.result == 'Ok') {
|
||||
$j('#fpsValue').text(respObj.monitor.FrameRate);
|
||||
setAlarmState(respObj.monitor.Status);
|
||||
} else {
|
||||
|
@ -556,20 +556,20 @@ function getAlarmCmdResponse(respObj, respText) {
|
|||
|
||||
function cmdDisableAlarms() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = 'disableAlarms';
|
||||
alarmCmdReq(data);
|
||||
}
|
||||
|
||||
function cmdEnableAlarms() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = 'enableAlarms';
|
||||
alarmCmdReq(data);
|
||||
}
|
||||
|
||||
function cmdAlarm() {
|
||||
if ( enableAlmBtn.hasClass('disabled') ) {
|
||||
if (enableAlmBtn.hasClass('disabled')) {
|
||||
cmdEnableAlarms();
|
||||
} else {
|
||||
cmdDisableAlarms();
|
||||
|
@ -578,23 +578,23 @@ function cmdAlarm() {
|
|||
|
||||
function cmdForceAlarm() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = 'forceAlarm';
|
||||
alarmCmdReq(data);
|
||||
if ( window.event ) window.event.preventDefault();
|
||||
if (window.event) window.event.preventDefault();
|
||||
}
|
||||
|
||||
function cmdCancelForcedAlarm() {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.command = 'cancelForcedAlarm';
|
||||
alarmCmdReq(data);
|
||||
if ( window.event ) window.event.preventDefault();
|
||||
if (window.event) window.event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function cmdForce() {
|
||||
if ( forceAlmBtn.hasClass('disabled') ) {
|
||||
if (forceAlmBtn.hasClass('disabled')) {
|
||||
cmdCancelForcedAlarm();
|
||||
} else {
|
||||
cmdForceAlarm();
|
||||
|
@ -608,11 +608,11 @@ function controlReq(data) {
|
|||
}
|
||||
|
||||
function getControlResponse(respObj, respText) {
|
||||
if ( !respObj ) {
|
||||
if (!respObj) {
|
||||
return;
|
||||
}
|
||||
//console.log( respText );
|
||||
if ( respObj.result != 'Ok' ) {
|
||||
if (respObj.result != 'Ok') {
|
||||
alert("Control response was status = "+respObj.status+"\nmessage = "+respObj.message);
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +633,7 @@ function controlCmd(event) {
|
|||
|
||||
var data = {};
|
||||
|
||||
if ( event && (xtell || ytell) ) {
|
||||
if (event && (xtell || ytell)) {
|
||||
var target = event.target;
|
||||
var offset = $j(target).offset();
|
||||
var width = $j(target).width();
|
||||
|
@ -642,45 +642,45 @@ function controlCmd(event) {
|
|||
var x = event.pageX - offset.left;
|
||||
var y = event.pageY - offset.top;
|
||||
|
||||
if ( xtell ) {
|
||||
if (xtell) {
|
||||
var xge = parseInt((x*100)/width);
|
||||
if ( xtell == -1 ) {
|
||||
if (xtell == -1) {
|
||||
xge = 100 - xge;
|
||||
} else if ( xtell == 2 ) {
|
||||
} else if (xtell == 2) {
|
||||
xge = 2*(50 - xge);
|
||||
}
|
||||
data.xge = xge;
|
||||
}
|
||||
if ( ytell ) {
|
||||
if (ytell) {
|
||||
var yge = parseInt((y*100)/height);
|
||||
if ( ytell == -1 ) {
|
||||
if (ytell == -1) {
|
||||
yge = 100 - yge;
|
||||
} else if ( ytell == 2 ) {
|
||||
} else if (ytell == 2) {
|
||||
yge = 2*(50 - yge);
|
||||
}
|
||||
data.yge = yge;
|
||||
}
|
||||
}
|
||||
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.control = control;
|
||||
controlReq(data);
|
||||
|
||||
if ( streamMode == 'single' ) {
|
||||
if (streamMode == 'single') {
|
||||
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||
}
|
||||
}
|
||||
|
||||
function controlCmdImage( x, y ) {
|
||||
function controlCmdImage(x, y) {
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.scale = scale;
|
||||
data.control = imageControlMode;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
controlReq(data);
|
||||
|
||||
if ( streamMode == 'single' ) {
|
||||
if (streamMode == 'single') {
|
||||
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||
}
|
||||
}
|
||||
|
@ -701,10 +701,10 @@ function handleClick(event) {
|
|||
var x = parseInt((event.pageX - pos.left) * scaleX);
|
||||
var y = parseInt((event.pageY - pos.top) * scaleY);
|
||||
|
||||
if ( showMode == 'events' || !imageControlMode ) {
|
||||
if (showMode == 'events' || !imageControlMode) {
|
||||
if ( event.shift ) {
|
||||
streamCmdPan(x, y);
|
||||
} else if ( event.ctrlKey ) {
|
||||
} else if (event.ctrlKey) {
|
||||
streamCmdZoomOut();
|
||||
} else {
|
||||
streamCmdZoomIn(x, y);
|
||||
|
@ -715,16 +715,16 @@ function handleClick(event) {
|
|||
}
|
||||
|
||||
function appletRefresh() {
|
||||
if ( streamStatus && (!streamStatus.paused && !streamStatus.delayed) ) {
|
||||
if (streamStatus && (!streamStatus.paused && !streamStatus.delayed)) {
|
||||
var streamImg = $j('#liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
if (streamImg) {
|
||||
var parent = streamImg.parent();
|
||||
streamImg.remove();
|
||||
streamImg.append(parent);
|
||||
} else {
|
||||
console.error("Nothing found for liveStream"+monitorId);
|
||||
}
|
||||
if ( appletRefreshTime ) {
|
||||
if (appletRefreshTime) {
|
||||
setTimeout(appletRefresh, appletRefreshTime*1000);
|
||||
}
|
||||
} else {
|
||||
|
@ -743,8 +743,8 @@ var watchdogFunctions = {
|
|||
};
|
||||
|
||||
//Make sure the various refreshes are still taking effect
|
||||
function watchdogCheck( type ) {
|
||||
if ( watchdogInactive[type] ) {
|
||||
function watchdogCheck(type) {
|
||||
if (watchdogInactive[type]) {
|
||||
console.log("Detected streamWatch of type: " + type + " stopped, restarting");
|
||||
watchdogFunctions[type]();
|
||||
watchdogInactive[type] = false;
|
||||
|
@ -753,7 +753,7 @@ function watchdogCheck( type ) {
|
|||
}
|
||||
}
|
||||
|
||||
function watchdogOk( type ) {
|
||||
function watchdogOk(type) {
|
||||
watchdogInactive[type] = false;
|
||||
}
|
||||
|
||||
|
@ -797,7 +797,7 @@ function getSettingsModal() {
|
|||
}
|
||||
|
||||
function processClicks(event, field, value, row, $element) {
|
||||
if ( field == 'Delete' ) {
|
||||
if (field == 'Delete') {
|
||||
$j.getJSON(monitorUrl + '?request=modal&modal=delconfirm')
|
||||
.done(function(data) {
|
||||
insertModalHtml('deleteConfirm', data.html);
|
||||
|
@ -812,7 +812,7 @@ function processClicks(event, field, value, row, $element) {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEdit.Events ) {
|
||||
if (!canEdit.Events) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ function manageDelConfirmModalBtns() {
|
|||
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+eid)
|
||||
.done( function(data) {
|
||||
.done(function(data) {
|
||||
table.bootstrapTable('refresh');
|
||||
$j('#deleteConfirm').modal('hide');
|
||||
})
|
||||
|
@ -838,7 +838,7 @@ function msieVer() {
|
|||
var ua = window.navigator.userAgent;
|
||||
var msie = ua.indexOf("MSIE ");
|
||||
|
||||
if ( msie >= 0 ) { // If Internet Explorer, return version number
|
||||
if (msie >= 0) { // If Internet Explorer, return version number
|
||||
return msie;
|
||||
} else { // If another browser, return 0
|
||||
return 0;
|
||||
|
@ -846,31 +846,31 @@ function msieVer() {
|
|||
}
|
||||
|
||||
function initPage() {
|
||||
if ( canView.Control ) {
|
||||
if (canView.Control) {
|
||||
// Load the PTZ Preset modal into the DOM
|
||||
if ( monitorControllable ) getCtrlPresetModal();
|
||||
if (monitorControllable) getCtrlPresetModal();
|
||||
// Load the settings modal into the DOM
|
||||
if ( monitorType == "Local" ) getSettingsModal();
|
||||
if (monitorType == "Local") getSettingsModal();
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
if ( streamMode == 'single' ) {
|
||||
statusCmdTimer = setTimeout(statusCmdQuery, (Math.random()+0.1)*statusRefreshTimeout );
|
||||
if (monitorType != 'WebSite') {
|
||||
if (streamMode == 'single') {
|
||||
statusCmdTimer = setTimeout(statusCmdQuery, (Math.random()+0.1)*statusRefreshTimeout);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'status');
|
||||
} else {
|
||||
streamCmdTimer = setTimeout(streamCmdQuery, (Math.random()+0.1)*statusRefreshTimeout );
|
||||
streamCmdTimer = setTimeout(streamCmdQuery, (Math.random()+0.1)*statusRefreshTimeout);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream');
|
||||
}
|
||||
|
||||
if ( canStreamNative || (streamMode == 'single') ) {
|
||||
if (canStreamNative || (streamMode == 'single')) {
|
||||
var streamImg = $j('#imageFeed img');
|
||||
if ( !streamImg ) {
|
||||
if (!streamImg) {
|
||||
streamImg = $j('#imageFeed object');
|
||||
}
|
||||
if ( !streamImg ) {
|
||||
if (!streamImg) {
|
||||
console.error('No streamImg found for imageFeed');
|
||||
} else {
|
||||
if ( streamMode == 'single' ) {
|
||||
if (streamMode == 'single') {
|
||||
streamImg.click(streamImg, fetchImage);
|
||||
setInterval(fetchImage, imageRefreshTimeout, $j('#imageFeed img'));
|
||||
} else {
|
||||
|
@ -881,17 +881,17 @@ function initPage() {
|
|||
} // end if have streamImg
|
||||
} // streamMode native or single
|
||||
|
||||
if ( refreshApplet && appletRefreshTime ) {
|
||||
if (refreshApplet && appletRefreshTime) {
|
||||
setTimeout(appletRefresh, appletRefreshTime*1000);
|
||||
}
|
||||
if ( window.history.length == 1 ) {
|
||||
if (window.history.length == 1) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
document.querySelectorAll('select[name="scale"]').forEach(function(el) {
|
||||
el.onchange = window['changeScale'];
|
||||
});
|
||||
changeScale();
|
||||
} else if ( monitorRefresh > 0 ) {
|
||||
} else if (monitorRefresh > 0) {
|
||||
setInterval(reloadWebSite, monitorRefresh*1000);
|
||||
}
|
||||
|
||||
|
@ -920,7 +920,7 @@ function initPage() {
|
|||
settingsBtn.prop('disabled', !(canView.Control && monitorType == 'Local'));
|
||||
|
||||
// Init the bootstrap-table
|
||||
if ( monitorType != 'WebSite' ) table.bootstrapTable({icons: icons});
|
||||
if (monitorType != 'WebSite') table.bootstrapTable({icons: icons});
|
||||
|
||||
// Update table rows each time after new data is loaded
|
||||
table.on('post-body.bs.table', function(data) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canEdit('Monitors') ) {
|
||||
if (!canEdit('Monitors')) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
@ -31,11 +31,9 @@ function probeV4L() {
|
|||
$command = getZmuCommand(' --query --device');
|
||||
if ( !empty($_REQUEST['device']) )
|
||||
$command .= '='.escapeshellarg($_REQUEST['device']);
|
||||
|
||||
$result = exec(escapeshellcmd($command), $output, $status);
|
||||
if ( $status ) {
|
||||
ZM\Error("Unable to probe local cameras using $command, status is '$status' " . implode("\n",$output));
|
||||
return $cameras;
|
||||
if ($status) {
|
||||
ZM\Warning("Errors while probe local cameras using $command, status is '$status' " . implode("\n", $output));
|
||||
}
|
||||
|
||||
$monitors = array();
|
||||
|
@ -325,15 +323,15 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );
|
|||
<div id="page">
|
||||
<h2><?php echo translate('MonitorProbe') ?></h2>
|
||||
<div id="content">
|
||||
<form name="contentForm" id="contentForm" method="post" action="?">
|
||||
<form name="contentForm" id="contentForm" method="get" action="?">
|
||||
<input type="hidden" name="view" value="none"/>
|
||||
<input type="hidden" name="mid" value="<?php echo validNum($_REQUEST['mid']) ?>"/>
|
||||
<input type="hidden" name="mid" value="<?php echo isset($_REQUEST['mid'])?validNum($_REQUEST['mid']):'' ?>"/>
|
||||
<p>
|
||||
<?php echo translate('MonitorProbeIntro') ?>
|
||||
</p>
|
||||
<p>
|
||||
<label for="probe"><?php echo translate('DetectedCameras') ?></label>
|
||||
<?php echo htmlSelect('probe', $cameras, null, array('data-on-change-this'=>'configureButtons(this)')); ?>
|
||||
<?php echo htmlSelect('probe', $cameras, null, array('data-on-change-this'=>'configureButtons')); ?>
|
||||
</p>
|
||||
<div id="contentButtons">
|
||||
<button type="button" name="saveBtn" value="Save" data-on-click-this="submitCamera" disabled="disabled">
|
||||
|
|
|
@ -231,7 +231,7 @@ foreach ( $monitors as $monitor ) {
|
|||
>
|
||||
<?php
|
||||
$monitor_options = $options;
|
||||
$monitor_options['width'] = $monitor_options['width'].'px';
|
||||
$monitor_options['width'] = $monitor_options['width']?$monitor_options['width'].'px' : null;
|
||||
$monitor_options['height'] = $monitor_options['height']?$monitor_options['height'].'px' : null;
|
||||
$monitor_options['connkey'] = $monitor->connKey();
|
||||
|
||||
|
|
|
@ -59,9 +59,8 @@ if ( !$snapshot->Id() ) {
|
|||
<button id="editBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Edit') ?>" disabled><i class="fa fa-pencil"></i></button>
|
||||
-->
|
||||
<button id="saveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Save') ?>"><i class="fa fa-save"></i></button>
|
||||
<!--
|
||||
<button id="exportBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Export') ?>"><i class="fa fa-external-link"></i></button>
|
||||
-->
|
||||
<button id="downloadBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Download') ?>" disabled><i class="fa fa-download"></i></button>
|
||||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>"><i class="fa fa-trash"></i></button>
|
||||
<?php } // end if snapshot->Id ?>
|
||||
</div>
|
||||
|
@ -96,6 +95,27 @@ if ( !$snapshot->Id() ) {
|
|||
?>
|
||||
</div><!--content-->
|
||||
<?php } // end if snapshot->Id() ?>
|
||||
</form>
|
||||
</div><!--page-->
|
||||
</form>
|
||||
<h2 id="downloadProgress" class="<?php
|
||||
if ( isset($_REQUEST['generated']) ) {
|
||||
if ( $_REQUEST['generated'] )
|
||||
echo 'infoText';
|
||||
else
|
||||
echo 'errorText';
|
||||
} else {
|
||||
echo 'hidden warnText';
|
||||
}
|
||||
?>">
|
||||
<span id="downloadProgressText">
|
||||
<?php
|
||||
if ( isset($_REQUEST['generated']) ) {
|
||||
if ( $_REQUEST['generated'] )
|
||||
echo translate('Download Succeeded');
|
||||
else
|
||||
echo translate('Download Failed');
|
||||
}
|
||||
?></span>
|
||||
<span id="downloadProgressTicker"></span>
|
||||
</h2>
|
||||
</div><!--page-->
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView('Events') ) {
|
||||
if (!(canView('Events') or canView('Snapshots'))) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
@ -53,9 +53,11 @@ if ( !$mimetype ) {
|
|||
}
|
||||
|
||||
$connkey = isset($_REQUEST['connkey'])?$_REQUEST['connkey']:'';
|
||||
$filename = "zmExport_$connkey.$file_ext";
|
||||
$filename = isset($_REQUEST['file'])?$_REQUEST['file']:"zmExport_$connkey.$file_ext";
|
||||
$filename = str_replace('/', '', $filename); # protect system files. must be a filename, not a path
|
||||
|
||||
$filename_path = ZM_DIR_EXPORTS.'/'.$filename;
|
||||
ZM\Debug("downloading archive from $filename_path");
|
||||
ZM\Debug('downloading archive from '.$filename_path);
|
||||
if ( is_readable($filename_path) ) {
|
||||
while (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue