Merge pull request #1255 from SteveGilvarry/feature-h264-videostorage

Merge master to feature-h264-videostorage
This commit is contained in:
Steve Gilvarry 2016-02-04 07:39:09 +11:00
commit 74687af1c7
72 changed files with 1534 additions and 1190 deletions

View File

@ -1,99 +1,129 @@
# Change Log # Change Log
## [Unreleased](https://github.com/ZoneMinder/ZoneMinder/tree/HEAD) ## [v1.29.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0) (2016-02-03)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.29.0-rc2...v1.29.0)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.28.1...HEAD)
**Closed issues:**
- Zoneminder Signal Loss event [\#964](https://github.com/ZoneMinder/ZoneMinder/issues/964)
- Default scale other than actual skews image [\#963](https://github.com/ZoneMinder/ZoneMinder/issues/963)
- Monitor configured with ffmpeg shows last part of URL instead of hostname in overview [\#950](https://github.com/ZoneMinder/ZoneMinder/issues/950)
- please update bundled CakePHP [\#945](https://github.com/ZoneMinder/ZoneMinder/issues/945)
- Montage shows only feed from the first camera [\#940](https://github.com/ZoneMinder/ZoneMinder/issues/940)
- zmtrigger: minor message format correction [\#939](https://github.com/ZoneMinder/ZoneMinder/issues/939)
- error starting zoneminder after latest upgrade [\#935](https://github.com/ZoneMinder/ZoneMinder/issues/935)
- Error "Attempt to directly assign buffer from an undersized buffer of size" [\#932](https://github.com/ZoneMinder/ZoneMinder/issues/932)
- External access to snapshots of cameras [\#929](https://github.com/ZoneMinder/ZoneMinder/issues/929)
- virtualbox - zoneminder shows only six cams [\#927](https://github.com/ZoneMinder/ZoneMinder/issues/927)
- zm\_update-1.28.99.sql not executable [\#924](https://github.com/ZoneMinder/ZoneMinder/issues/924)
- m [\#922](https://github.com/ZoneMinder/ZoneMinder/issues/922)
- loop recording [\#914](https://github.com/ZoneMinder/ZoneMinder/issues/914)
- Implement Passive Source Type for Cams that Support Event Uploading [\#912](https://github.com/ZoneMinder/ZoneMinder/issues/912)
- incorrect encoding of Russian language [\#907](https://github.com/ZoneMinder/ZoneMinder/issues/907)
- Can't compile Zoneminder v1.28.1 [\#904](https://github.com/ZoneMinder/ZoneMinder/issues/904)
- Add isRunning field to States [\#898](https://github.com/ZoneMinder/ZoneMinder/issues/898)
- updated 9831W control script [\#893](https://github.com/ZoneMinder/ZoneMinder/issues/893)
- 404 error on Ubuntu 14.04 install [\#889](https://github.com/ZoneMinder/ZoneMinder/issues/889)
- Video Smear - Vertical Striping [\#888](https://github.com/ZoneMinder/ZoneMinder/issues/888)
- Zoneminder mobile theme broken. [\#887](https://github.com/ZoneMinder/ZoneMinder/issues/887)
- cgi-bin -\> symlink on zms not work for me \(Gentoo/SystemD\) [\#878](https://github.com/ZoneMinder/ZoneMinder/issues/878)
- Replay Event Stuck [\#869](https://github.com/ZoneMinder/ZoneMinder/issues/869)
- cant add or edit monitor [\#868](https://github.com/ZoneMinder/ZoneMinder/issues/868)
- Odd window size differences when viewing frame alarm image between Chrome & FF [\#865](https://github.com/ZoneMinder/ZoneMinder/issues/865)
- On ubuntu 14.04 zoneminder 1.28.1 alarm never terminate!! [\#852](https://github.com/ZoneMinder/ZoneMinder/issues/852)
- X-10 configuration not working ZM V1.28.1 [\#848](https://github.com/ZoneMinder/ZoneMinder/issues/848)
- Global symbol requires explicit package name... [\#846](https://github.com/ZoneMinder/ZoneMinder/issues/846)
- Adapt to changes in Ubuntu 15.04 [\#840](https://github.com/ZoneMinder/ZoneMinder/issues/840)
- After initial setup, unable to start again [\#839](https://github.com/ZoneMinder/ZoneMinder/issues/839)
- FFMPEG path finding error \(formerly: Are you switching to a totally CMake based build?\) [\#835](https://github.com/ZoneMinder/ZoneMinder/issues/835)
- Purchase a Raspberry Pi 2 + PiCam for ZoneMinder development \[$114\] [\#832](https://github.com/ZoneMinder/ZoneMinder/issues/832)
- Can't Login Web getting a Loop [\#831](https://github.com/ZoneMinder/ZoneMinder/issues/831)
- Missing function drop down values \(db issue?\) [\#828](https://github.com/ZoneMinder/ZoneMinder/issues/828)
- curl using HEAD instead of GET for http requests results in 404 on some servers [\#827](https://github.com/ZoneMinder/ZoneMinder/issues/827)
- Empty string if missing index in lang files [\#819](https://github.com/ZoneMinder/ZoneMinder/issues/819)
- fix for RTSP streaming over UDP [\#811](https://github.com/ZoneMinder/ZoneMinder/issues/811)
- bundled CakePHP overhead [\#810](https://github.com/ZoneMinder/ZoneMinder/issues/810)
- PHP session locks serialize access to all scripts causing UI hangs [\#806](https://github.com/ZoneMinder/ZoneMinder/issues/806)
- How do I add authentication to ZM APIs? [\#797](https://github.com/ZoneMinder/ZoneMinder/issues/797)
- Add man page for zmsystemctl.pl [\#788](https://github.com/ZoneMinder/ZoneMinder/issues/788)
- man pages please; improve --help option [\#787](https://github.com/ZoneMinder/ZoneMinder/issues/787)
- ZM\_CONTENTDIR issues [\#786](https://github.com/ZoneMinder/ZoneMinder/issues/786)
- please update bundled jQuery [\#785](https://github.com/ZoneMinder/ZoneMinder/issues/785)
- please update bundled Mootools [\#784](https://github.com/ZoneMinder/ZoneMinder/issues/784)
- duplicated files in `cgi-bin` [\#777](https://github.com/ZoneMinder/ZoneMinder/issues/777)
- FTBFS on kFreeBSD [\#771](https://github.com/ZoneMinder/ZoneMinder/issues/771)
- CMake: incorrect installation of Perl modules \[patch\] [\#769](https://github.com/ZoneMinder/ZoneMinder/issues/769)
- Issue when viewing events when users are restricted to limited cameras [\#766](https://github.com/ZoneMinder/ZoneMinder/issues/766)
- zmupdate.pl: ignores ZM\_SERVER\_HOST in zm.conf [\#765](https://github.com/ZoneMinder/ZoneMinder/issues/765)
- Remote Zoneminder installations [\#764](https://github.com/ZoneMinder/ZoneMinder/issues/764)
- source code mess [\#760](https://github.com/ZoneMinder/ZoneMinder/issues/760)
- bttv crashing zoneminder rpm [\#755](https://github.com/ZoneMinder/ZoneMinder/issues/755)
- Make Uninstall no longer removes Perl modules [\#753](https://github.com/ZoneMinder/ZoneMinder/issues/753)
- Playback video problem in v1.26.5 [\#752](https://github.com/ZoneMinder/ZoneMinder/issues/752)
- Integrate Make Movie Branch [\#747](https://github.com/ZoneMinder/ZoneMinder/issues/747)
- FI8620 ERR Error while decoding frame [\#741](https://github.com/ZoneMinder/ZoneMinder/issues/741)
- \[Critical\] 1.28.0 to 1.28.1 seems to have lost ability for RTSP Authentication [\#738](https://github.com/ZoneMinder/ZoneMinder/issues/738)
- Disabling cambozola in options doesn't actually disable? [\#735](https://github.com/ZoneMinder/ZoneMinder/issues/735)
- FI9821W v2 shows blue screen [\#734](https://github.com/ZoneMinder/ZoneMinder/issues/734)
- Configure script checking for netpbm [\#731](https://github.com/ZoneMinder/ZoneMinder/issues/731)
- Missing dependency for killall in rpm package [\#727](https://github.com/ZoneMinder/ZoneMinder/issues/727)
- Build with ZM\_TARGET\_DISTRO=el7 fails to start under systemd [\#724](https://github.com/ZoneMinder/ZoneMinder/issues/724)
- Issue with event page for users with restricted monitors [\#717](https://github.com/ZoneMinder/ZoneMinder/issues/717)
- Unrecognised content type 'video/x-ms-asf' [\#716](https://github.com/ZoneMinder/ZoneMinder/issues/716)
- Flat skin stopped working [\#715](https://github.com/ZoneMinder/ZoneMinder/issues/715)
- Zone edit dots are gone [\#712](https://github.com/ZoneMinder/ZoneMinder/issues/712)
- zm\_rtsp Use of avformat\_free\_context not version checked [\#710](https://github.com/ZoneMinder/ZoneMinder/issues/710)
- Unable to generate video, check /usr/share/zoneminder/events/1/15/02/15/20/10/00/ffmpeg.log for details [\#705](https://github.com/ZoneMinder/ZoneMinder/issues/705)
- Axis M5014 PTZ Control [\#703](https://github.com/ZoneMinder/ZoneMinder/issues/703)
- 2nd network port breaks 'Probe' in 1.28 on Ubuntu 14.04LTS? [\#698](https://github.com/ZoneMinder/ZoneMinder/issues/698)
- ZM's Develop actually [\#697](https://github.com/ZoneMinder/ZoneMinder/issues/697)
- Release 1.28.1 [\#693](https://github.com/ZoneMinder/ZoneMinder/issues/693)
- Image disappears \(flickers\) in monitor and event playback [\#689](https://github.com/ZoneMinder/ZoneMinder/issues/689)
- Multiple issues.. [\#688](https://github.com/ZoneMinder/ZoneMinder/issues/688)
- short PHP open tags paragraph on zoneminder.com Troubleshooting page [\#684](https://github.com/ZoneMinder/ZoneMinder/issues/684)
- The monitorprobe.php code does not work in FreeBSD [\#683](https://github.com/ZoneMinder/ZoneMinder/issues/683)
- ZoneMinder problem [\#680](https://github.com/ZoneMinder/ZoneMinder/issues/680)
- CMAKE ZM\_PERL\_SUBPREFIX Slash Issue [\#677](https://github.com/ZoneMinder/ZoneMinder/issues/677)
- Centos 6.5 crashes [\#619](https://github.com/ZoneMinder/ZoneMinder/issues/619)
- ZMS crashes after "Attempt to directly assign buffer from an undersized buffer of size" error [\#586](https://github.com/ZoneMinder/ZoneMinder/issues/586)
- hi all, i'm under Linux Gentoo with systemd - ZM v1.27.99.0 [\#511](https://github.com/ZoneMinder/ZoneMinder/issues/511)
- Event export with ZM\_USE\_DEEP\_STORAGE option set [\#506](https://github.com/ZoneMinder/ZoneMinder/issues/506)
- Streaming not working on Chrome when authentication is ON [\#328](https://github.com/ZoneMinder/ZoneMinder/issues/328)
- Can add a simple send mail function [\#311](https://github.com/ZoneMinder/ZoneMinder/issues/311)
**Merged pull requests:** **Merged pull requests:**
- 1253 zms quit cmd [\#1254](https://github.com/ZoneMinder/ZoneMinder/pull/1254) ([pliablepixels](https://github.com/pliablepixels))
- Add Debug/Info lines reporting multi-server status [\#1252](https://github.com/ZoneMinder/ZoneMinder/pull/1252) ([connortechnology](https://github.com/connortechnology))
- Do debian package mods [\#1244](https://github.com/ZoneMinder/ZoneMinder/pull/1244) ([pliablepixels](https://github.com/pliablepixels))
- zmtrigger - process off+time delay condition [\#1240](https://github.com/ZoneMinder/ZoneMinder/pull/1240) ([knnniggett](https://github.com/knnniggett))
- Multi server [\#1233](https://github.com/ZoneMinder/ZoneMinder/pull/1233) ([connortechnology](https://github.com/connortechnology))
- remove Google open Sans external import [\#1232](https://github.com/ZoneMinder/ZoneMinder/pull/1232) ([connortechnology](https://github.com/connortechnology))
- PTZ - Added autostop to Down command on FI8918W [\#1189](https://github.com/ZoneMinder/ZoneMinder/pull/1189) ([marcolino7](https://github.com/marcolino7))
## [v1.29.0-rc2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0-rc2) (2016-01-05)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.29.0-rc1...v1.29.0-rc2)
**Merged pull requests:**
- Multi server [\#1223](https://github.com/ZoneMinder/ZoneMinder/pull/1223) ([connortechnology](https://github.com/connortechnology))
- Multi server [\#1222](https://github.com/ZoneMinder/ZoneMinder/pull/1222) ([connortechnology](https://github.com/connortechnology))
- Multi server [\#1217](https://github.com/ZoneMinder/ZoneMinder/pull/1217) ([connortechnology](https://github.com/connortechnology))
- Multi server [\#1215](https://github.com/ZoneMinder/ZoneMinder/pull/1215) ([connortechnology](https://github.com/connortechnology))
- Change log updates [\#1172](https://github.com/ZoneMinder/ZoneMinder/pull/1172) ([SteveGilvarry](https://github.com/SteveGilvarry))
## [v1.29.0-rc1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0-rc1) (2016-01-01)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.28.1...v1.29.0-rc1)
**Merged pull requests:**
- Bump version to 1.29.0 [\#1213](https://github.com/ZoneMinder/ZoneMinder/pull/1213) ([knnniggett](https://github.com/knnniggett))
- Missing rtd theme [\#1202](https://github.com/ZoneMinder/ZoneMinder/pull/1202) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Skip directories that have non-digits in them [\#1201](https://github.com/ZoneMinder/ZoneMinder/pull/1201) ([connortechnology](https://github.com/connortechnology))
- updated mobile app info [\#1200](https://github.com/ZoneMinder/ZoneMinder/pull/1200) ([pliablepixels](https://github.com/pliablepixels))
- Api more security [\#1196](https://github.com/ZoneMinder/ZoneMinder/pull/1196) ([pliablepixels](https://github.com/pliablepixels))
- Documentation [\#1194](https://github.com/ZoneMinder/ZoneMinder/pull/1194) ([pliablepixels](https://github.com/pliablepixels))
- Documentation updated for ubuntu [\#1193](https://github.com/ZoneMinder/ZoneMinder/pull/1193) ([pliablepixels](https://github.com/pliablepixels))
- Fixes \#1179 Libvlc Live555 Segmentation Fault [\#1190](https://github.com/ZoneMinder/ZoneMinder/pull/1190) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Add code to detect the change in REALM from older to newer firmware [\#1184](https://github.com/ZoneMinder/ZoneMinder/pull/1184) ([connortechnology](https://github.com/connortechnology))
- add a 1/8th scale option, which is useful for 1920x1080 streams [\#1182](https://github.com/ZoneMinder/ZoneMinder/pull/1182) ([connortechnology](https://github.com/connortechnology))
- Zms socket lock [\#1180](https://github.com/ZoneMinder/ZoneMinder/pull/1180) ([connortechnology](https://github.com/connortechnology))
- Check for the presence of CrudControllerTrait.php instead of .git [\#1178](https://github.com/ZoneMinder/ZoneMinder/pull/1178) ([knnniggett](https://github.com/knnniggett))
- Partial fix for \#1167 [\#1176](https://github.com/ZoneMinder/ZoneMinder/pull/1176) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Error on missing submodules [\#1173](https://github.com/ZoneMinder/ZoneMinder/pull/1173) ([knnniggett](https://github.com/knnniggett))
- fix mem alloc fault in zm\_monitor.cpp [\#1168](https://github.com/ZoneMinder/ZoneMinder/pull/1168) ([knnniggett](https://github.com/knnniggett))
- compat for php 5.4 [\#1164](https://github.com/ZoneMinder/ZoneMinder/pull/1164) ([abishai](https://github.com/abishai))
- remove comment at end of line [\#1157](https://github.com/ZoneMinder/ZoneMinder/pull/1157) ([connortechnology](https://github.com/connortechnology))
- Reorder RTSPDescribe to avoid -wreorder warnings [\#1147](https://github.com/ZoneMinder/ZoneMinder/pull/1147) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Update to \#1137 for backward compatibility. [\#1142](https://github.com/ZoneMinder/ZoneMinder/pull/1142) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Update Travis to ffmpeg 2.8.1 for testing [\#1139](https://github.com/ZoneMinder/ZoneMinder/pull/1139) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Replace deprecated FFmpeg API [\#1137](https://github.com/ZoneMinder/ZoneMinder/pull/1137) ([onlyjob](https://github.com/onlyjob))
- added prev/next event ids [\#1136](https://github.com/ZoneMinder/ZoneMinder/pull/1136) ([pliablepixels](https://github.com/pliablepixels))
- Install nph-zms with FILES so it is listed in install\_manifest.txt [\#1124](https://github.com/ZoneMinder/ZoneMinder/pull/1124) ([baffo32](https://github.com/baffo32))
- Stray semicolon causes SQL error [\#1123](https://github.com/ZoneMinder/ZoneMinder/pull/1123) ([baffo32](https://github.com/baffo32))
- Use relative URL's instead of absolute [\#1121](https://github.com/ZoneMinder/ZoneMinder/pull/1121) ([knnniggett](https://github.com/knnniggett))
- Update version check URL [\#1120](https://github.com/ZoneMinder/ZoneMinder/pull/1120) ([kylejohnson](https://github.com/kylejohnson))
- Add index to frames [\#1116](https://github.com/ZoneMinder/ZoneMinder/pull/1116) ([kylejohnson](https://github.com/kylejohnson))
- Fatal if content dirs are unwritable [\#1113](https://github.com/ZoneMinder/ZoneMinder/pull/1113) ([baffo32](https://github.com/baffo32))
- Fatal error if date.timezone is unset [\#1111](https://github.com/ZoneMinder/ZoneMinder/pull/1111) ([baffo32](https://github.com/baffo32))
- Fix faulty zm.conf.new install line [\#1107](https://github.com/ZoneMinder/ZoneMinder/pull/1107) ([baffo32](https://github.com/baffo32))
- Update preinst [\#1103](https://github.com/ZoneMinder/ZoneMinder/pull/1103) ([seebaer1976](https://github.com/seebaer1976))
- Update apache.conf [\#1102](https://github.com/ZoneMinder/ZoneMinder/pull/1102) ([seebaer1976](https://github.com/seebaer1976))
- Update rules [\#1101](https://github.com/ZoneMinder/ZoneMinder/pull/1101) ([seebaer1976](https://github.com/seebaer1976))
- Update links [\#1100](https://github.com/ZoneMinder/ZoneMinder/pull/1100) ([seebaer1976](https://github.com/seebaer1976))
- Update preinst [\#1099](https://github.com/ZoneMinder/ZoneMinder/pull/1099) ([seebaer1976](https://github.com/seebaer1976))
- Fix zmaudit [\#1095](https://github.com/ZoneMinder/ZoneMinder/pull/1095) ([connortechnology](https://github.com/connortechnology))
- fixed version compare logic [\#1094](https://github.com/ZoneMinder/ZoneMinder/pull/1094) ([pliablepixels](https://github.com/pliablepixels))
- Don't install zm.conf if it already exists [\#1090](https://github.com/ZoneMinder/ZoneMinder/pull/1090) ([connortechnology](https://github.com/connortechnology))
- change types and move things around to remove compile warnings [\#1089](https://github.com/ZoneMinder/ZoneMinder/pull/1089) ([connortechnology](https://github.com/connortechnology))
- Tz [\#1084](https://github.com/ZoneMinder/ZoneMinder/pull/1084) ([connortechnology](https://github.com/connortechnology))
- fixed orange display for monitor mode [\#1083](https://github.com/ZoneMinder/ZoneMinder/pull/1083) ([pliablepixels](https://github.com/pliablepixels))
- use deleteAll\(\) vs. delete\(\) when deleting an Event's Frames [\#1080](https://github.com/ZoneMinder/ZoneMinder/pull/1080) ([kylejohnson](https://github.com/kylejohnson))
- Added control script for SunEyes SP-P1802SWPTZ [\#1079](https://github.com/ZoneMinder/ZoneMinder/pull/1079) ([bofhdk](https://github.com/bofhdk))
- Use the 3.0 branch of crud, compatible with cakephp 2.x [\#1078](https://github.com/ZoneMinder/ZoneMinder/pull/1078) ([kylejohnson](https://github.com/kylejohnson))
- 663 frames primary key [\#1075](https://github.com/ZoneMinder/ZoneMinder/pull/1075) ([kylejohnson](https://github.com/kylejohnson))
- Delete fixes for Events [\#1073](https://github.com/ZoneMinder/ZoneMinder/pull/1073) ([pliablepixels](https://github.com/pliablepixels))
- restart monitor when edited via APIs [\#1070](https://github.com/ZoneMinder/ZoneMinder/pull/1070) ([pliablepixels](https://github.com/pliablepixels))
- add debug statements for when LastWriteTime is not defined. [\#1067](https://github.com/ZoneMinder/ZoneMinder/pull/1067) ([connortechnology](https://github.com/connortechnology))
- fixed recaptcha showing up pre DB update [\#1066](https://github.com/ZoneMinder/ZoneMinder/pull/1066) ([pliablepixels](https://github.com/pliablepixels))
- fixed security instructions for curl [\#1062](https://github.com/ZoneMinder/ZoneMinder/pull/1062) ([pliablepixels](https://github.com/pliablepixels))
- header typo corrections [\#1058](https://github.com/ZoneMinder/ZoneMinder/pull/1058) ([onlyjob](https://github.com/onlyjob))
- quick fix for \#1055: make sure our mmap fd is \> 2 [\#1057](https://github.com/ZoneMinder/ZoneMinder/pull/1057) ([connortechnology](https://github.com/connortechnology))
- Fix sgfault caused by the privacy mask stuff [\#1056](https://github.com/ZoneMinder/ZoneMinder/pull/1056) ([connortechnology](https://github.com/connortechnology))
- link to cambozola pacakge, rather than download during build [\#1054](https://github.com/ZoneMinder/ZoneMinder/pull/1054) ([knnniggett](https://github.com/knnniggett))
- redhat rpm packaging modifications [\#1052](https://github.com/ZoneMinder/ZoneMinder/pull/1052) ([knnniggett](https://github.com/knnniggett))
- remove core.php, modify core.php.default [\#1049](https://github.com/ZoneMinder/ZoneMinder/pull/1049) ([knnniggett](https://github.com/knnniggett))
- Google recaptcha [\#1048](https://github.com/ZoneMinder/ZoneMinder/pull/1048) ([pliablepixels](https://github.com/pliablepixels))
- enable/disable RTSP Describe Header [\#1045](https://github.com/ZoneMinder/ZoneMinder/pull/1045) ([knnniggett](https://github.com/knnniggett))
- Add Documentation for Privacy zones [\#1044](https://github.com/ZoneMinder/ZoneMinder/pull/1044) ([schrorg](https://github.com/schrorg))
- added note about potential Perl and PHP time translation conflict wit… [\#1043](https://github.com/ZoneMinder/ZoneMinder/pull/1043) ([pliablepixels](https://github.com/pliablepixels))
- Multi server [\#1040](https://github.com/ZoneMinder/ZoneMinder/pull/1040) ([connortechnology](https://github.com/connortechnology))
- 1038 fixing state mgmt 1030 is active fix [\#1039](https://github.com/ZoneMinder/ZoneMinder/pull/1039) ([pliablepixels](https://github.com/pliablepixels))
- Grey color for disabled buttons [\#1037](https://github.com/ZoneMinder/ZoneMinder/pull/1037) ([pliablepixels](https://github.com/pliablepixels))
- Update filterevents.rst [\#1035](https://github.com/ZoneMinder/ZoneMinder/pull/1035) ([tikismoke](https://github.com/tikismoke))
- add warning and help text for maxfps fields [\#1033](https://github.com/ZoneMinder/ZoneMinder/pull/1033) ([knnniggett](https://github.com/knnniggett))
- update doc [\#1032](https://github.com/ZoneMinder/ZoneMinder/pull/1032) ([tikismoke](https://github.com/tikismoke))
- Remove full path from Logger filename [\#1029](https://github.com/ZoneMinder/ZoneMinder/pull/1029) ([knnniggett](https://github.com/knnniggett))
- Typo in README.md [\#1027](https://github.com/ZoneMinder/ZoneMinder/pull/1027) ([tikismoke](https://github.com/tikismoke))
- Add new zone type - privacy zones [\#1026](https://github.com/ZoneMinder/ZoneMinder/pull/1026) ([schrorg](https://github.com/schrorg))
- Send login activity to the zoneminder event log [\#1021](https://github.com/ZoneMinder/ZoneMinder/pull/1021) ([knnniggett](https://github.com/knnniggett))
- Small dark CSS fixes in frames and timeline view [\#1019](https://github.com/ZoneMinder/ZoneMinder/pull/1019) ([schrorg](https://github.com/schrorg))
- New User Permission "Groups" [\#1018](https://github.com/ZoneMinder/ZoneMinder/pull/1018) ([knnniggett](https://github.com/knnniggett))
- 1013 document migration [\#1017](https://github.com/ZoneMinder/ZoneMinder/pull/1017) ([pliablepixels](https://github.com/pliablepixels))
- Fix issue with score values less than 0 [\#1016](https://github.com/ZoneMinder/ZoneMinder/pull/1016) ([knnniggett](https://github.com/knnniggett))
- Explained a caveat with using relative times [\#1012](https://github.com/ZoneMinder/ZoneMinder/pull/1012) ([pliablepixels](https://github.com/pliablepixels))
- Included logic to not enforce authentication in API layer if ZM auth is off [\#1008](https://github.com/ZoneMinder/ZoneMinder/pull/1008) ([pliablepixels](https://github.com/pliablepixels))
- Update to ffmpeg 2.7.2 in travis build [\#1007](https://github.com/ZoneMinder/ZoneMinder/pull/1007) ([SteveGilvarry](https://github.com/SteveGilvarry))
- I was using the wrong field to check for portal authentication [\#1006](https://github.com/ZoneMinder/ZoneMinder/pull/1006) ([pliablepixels](https://github.com/pliablepixels))
- Demote user auth info message to debug [\#1003](https://github.com/ZoneMinder/ZoneMinder/pull/1003) ([Linwood-F](https://github.com/Linwood-F))
- Add scale as optional feature to image.php [\#1001](https://github.com/ZoneMinder/ZoneMinder/pull/1001) ([Linwood-F](https://github.com/Linwood-F))
- 995 events count per api \(bumps up \# of events reported per API call\) [\#996](https://github.com/ZoneMinder/ZoneMinder/pull/996) ([pliablepixels](https://github.com/pliablepixels))
- APIs will be served only if user is logged into the ZM portal [\#994](https://github.com/ZoneMinder/ZoneMinder/pull/994) ([pliablepixels](https://github.com/pliablepixels))
- Add option to make TimeStamp larger [\#992](https://github.com/ZoneMinder/ZoneMinder/pull/992) ([schrorg](https://github.com/schrorg))
- Implemented \#989 \(highlight current row in tables\) for dark CSS [\#990](https://github.com/ZoneMinder/ZoneMinder/pull/990) ([schrorg](https://github.com/schrorg))
- CSS\[skins/classic\]: highlight current row in tables. [\#989](https://github.com/ZoneMinder/ZoneMinder/pull/989) ([onlyjob](https://github.com/onlyjob))
- quiet error when no Servers in Servers table [\#986](https://github.com/ZoneMinder/ZoneMinder/pull/986) ([connortechnology](https://github.com/connortechnology))
- fix \#948 1 [\#985](https://github.com/ZoneMinder/ZoneMinder/pull/985) ([connortechnology](https://github.com/connortechnology))
- Remove shared data warning for purpose query only [\#984](https://github.com/ZoneMinder/ZoneMinder/pull/984) ([Linwood-F](https://github.com/Linwood-F))
- Change from info to debug [\#983](https://github.com/ZoneMinder/ZoneMinder/pull/983) ([Linwood-F](https://github.com/Linwood-F))
- Fix image dimensions check [\#980](https://github.com/ZoneMinder/ZoneMinder/pull/980) ([connortechnology](https://github.com/connortechnology))
- Apache.conf modifications [\#968](https://github.com/ZoneMinder/ZoneMinder/pull/968) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Dark CSS for classic theme [\#967](https://github.com/ZoneMinder/ZoneMinder/pull/967) ([schrorg](https://github.com/schrorg))
- Auto generated changelog [\#966](https://github.com/ZoneMinder/ZoneMinder/pull/966) ([SteveGilvarry](https://github.com/SteveGilvarry))
- 959 add exif date time to images [\#962](https://github.com/ZoneMinder/ZoneMinder/pull/962) ([Linwood-F](https://github.com/Linwood-F))
- Add analysis interval parameter to monitors settings [\#956](https://github.com/ZoneMinder/ZoneMinder/pull/956) ([manupap1](https://github.com/manupap1))
- Fixed Configs API to return all values [\#955](https://github.com/ZoneMinder/ZoneMinder/pull/955) ([pliablepixels](https://github.com/pliablepixels)) - Fixed Configs API to return all values [\#955](https://github.com/ZoneMinder/ZoneMinder/pull/955) ([pliablepixels](https://github.com/pliablepixels))
- Change encoding of german language file to UTF-8 [\#952](https://github.com/ZoneMinder/ZoneMinder/pull/952) ([schrorg](https://github.com/schrorg)) - Change encoding of german language file to UTF-8 [\#952](https://github.com/ZoneMinder/ZoneMinder/pull/952) ([schrorg](https://github.com/schrorg))
- Show correct part of URL \(hostname\) for ffmpeg sources in console [\#951](https://github.com/ZoneMinder/ZoneMinder/pull/951) ([schrorg](https://github.com/schrorg)) - Show correct part of URL \(hostname\) for ffmpeg sources in console [\#951](https://github.com/ZoneMinder/ZoneMinder/pull/951) ([schrorg](https://github.com/schrorg))
@ -125,17 +155,12 @@
- Generate man pages for perl scripts & C Binaries in the bin folder [\#896](https://github.com/ZoneMinder/ZoneMinder/pull/896) ([knnniggett](https://github.com/knnniggett)) - Generate man pages for perl scripts & C Binaries in the bin folder [\#896](https://github.com/ZoneMinder/ZoneMinder/pull/896) ([knnniggett](https://github.com/knnniggett))
- 893 foscam 9831 w and other foscams [\#895](https://github.com/ZoneMinder/ZoneMinder/pull/895) ([pliablepixels](https://github.com/pliablepixels)) - 893 foscam 9831 w and other foscams [\#895](https://github.com/ZoneMinder/ZoneMinder/pull/895) ([pliablepixels](https://github.com/pliablepixels))
- 893 foscam 9831 w and other foscams [\#894](https://github.com/ZoneMinder/ZoneMinder/pull/894) ([pliablepixels](https://github.com/pliablepixels)) - 893 foscam 9831 w and other foscams [\#894](https://github.com/ZoneMinder/ZoneMinder/pull/894) ([pliablepixels](https://github.com/pliablepixels))
- improve debugging for analysis check and restart if can't read shared data [\#892](https://github.com/ZoneMinder/ZoneMinder/pull/892) ([connortechnology](https://github.com/connortechnology))
- Zmwatch cleanup2 [\#891](https://github.com/ZoneMinder/ZoneMinder/pull/891) ([connortechnology](https://github.com/connortechnology)) - Zmwatch cleanup2 [\#891](https://github.com/ZoneMinder/ZoneMinder/pull/891) ([connortechnology](https://github.com/connortechnology))
- reverse the if statement to reduce indenting [\#890](https://github.com/ZoneMinder/ZoneMinder/pull/890) ([connortechnology](https://github.com/connortechnology)) - reverse the if statement to reduce indenting [\#890](https://github.com/ZoneMinder/ZoneMinder/pull/890) ([connortechnology](https://github.com/connortechnology))
- Updated API document [\#886](https://github.com/ZoneMinder/ZoneMinder/pull/886) ([pliablepixels](https://github.com/pliablepixels)) - Updated API document [\#886](https://github.com/ZoneMinder/ZoneMinder/pull/886) ([pliablepixels](https://github.com/pliablepixels))
- Use avconv as alternative to ffmpeg executable [\#884](https://github.com/ZoneMinder/ZoneMinder/pull/884) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Use avconv as alternative to ffmpeg executable [\#884](https://github.com/ZoneMinder/ZoneMinder/pull/884) ([SteveGilvarry](https://github.com/SteveGilvarry))
- 881 bootstrap loading config [\#883](https://github.com/ZoneMinder/ZoneMinder/pull/883) ([pliablepixels](https://github.com/pliablepixels)) - 881 bootstrap loading config [\#883](https://github.com/ZoneMinder/ZoneMinder/pull/883) ([pliablepixels](https://github.com/pliablepixels))
- Merged Angular UI branch API to master [\#882](https://github.com/ZoneMinder/ZoneMinder/pull/882) ([pliablepixels](https://github.com/pliablepixels)) - Merged Angular UI branch API to master [\#882](https://github.com/ZoneMinder/ZoneMinder/pull/882) ([pliablepixels](https://github.com/pliablepixels))
- h264 GUI translate fixes [\#880](https://github.com/ZoneMinder/ZoneMinder/pull/880) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Merging Master to feature-h264-videostorage [\#879](https://github.com/ZoneMinder/ZoneMinder/pull/879) ([SteveGilvarry](https://github.com/SteveGilvarry))
- 799 api improvements [\#877](https://github.com/ZoneMinder/ZoneMinder/pull/877) ([pliablepixels](https://github.com/pliablepixels))
- Fixed daemonStatus API to return string returned by ZMC in addition t… [\#876](https://github.com/ZoneMinder/ZoneMinder/pull/876) ([pliablepixels](https://github.com/pliablepixels))
- Add version to the startup log line [\#875](https://github.com/ZoneMinder/ZoneMinder/pull/875) ([connortechnology](https://github.com/connortechnology)) - Add version to the startup log line [\#875](https://github.com/ZoneMinder/ZoneMinder/pull/875) ([connortechnology](https://github.com/connortechnology))
- German translation update [\#874](https://github.com/ZoneMinder/ZoneMinder/pull/874) ([seeebek](https://github.com/seeebek)) - German translation update [\#874](https://github.com/ZoneMinder/ZoneMinder/pull/874) ([seeebek](https://github.com/seeebek))
- reduce the wait to 2/10ths instead of a whole second [\#873](https://github.com/ZoneMinder/ZoneMinder/pull/873) ([connortechnology](https://github.com/connortechnology)) - reduce the wait to 2/10ths instead of a whole second [\#873](https://github.com/ZoneMinder/ZoneMinder/pull/873) ([connortechnology](https://github.com/connortechnology))
@ -186,8 +211,6 @@
- POD: zmupdate.pl converted to "pod2usage" [\#763](https://github.com/ZoneMinder/ZoneMinder/pull/763) ([onlyjob](https://github.com/onlyjob)) - POD: zmupdate.pl converted to "pod2usage" [\#763](https://github.com/ZoneMinder/ZoneMinder/pull/763) ([onlyjob](https://github.com/onlyjob))
- build: fix FTBFS with format-hardening \(please review\) [\#761](https://github.com/ZoneMinder/ZoneMinder/pull/761) ([onlyjob](https://github.com/onlyjob)) - build: fix FTBFS with format-hardening \(please review\) [\#761](https://github.com/ZoneMinder/ZoneMinder/pull/761) ([onlyjob](https://github.com/onlyjob))
- fixing POD errors [\#759](https://github.com/ZoneMinder/ZoneMinder/pull/759) ([onlyjob](https://github.com/onlyjob)) - fixing POD errors [\#759](https://github.com/ZoneMinder/ZoneMinder/pull/759) ([onlyjob](https://github.com/onlyjob))
- Fixed a missing bracket post merge and also SQL\_values now used for Even... [\#750](https://github.com/ZoneMinder/ZoneMinder/pull/750) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Keeping h264 updated. [\#749](https://github.com/ZoneMinder/ZoneMinder/pull/749) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Ignore autogenerated files in git [\#746](https://github.com/ZoneMinder/ZoneMinder/pull/746) ([manupap1](https://github.com/manupap1)) - Ignore autogenerated files in git [\#746](https://github.com/ZoneMinder/ZoneMinder/pull/746) ([manupap1](https://github.com/manupap1))
- when auth is needed, try command again before dying. [\#739](https://github.com/ZoneMinder/ZoneMinder/pull/739) ([connortechnology](https://github.com/connortechnology)) - when auth is needed, try command again before dying. [\#739](https://github.com/ZoneMinder/ZoneMinder/pull/739) ([connortechnology](https://github.com/connortechnology))
- remove NETPBM dependency from autotools [\#737](https://github.com/ZoneMinder/ZoneMinder/pull/737) ([knnniggett](https://github.com/knnniggett)) - remove NETPBM dependency from autotools [\#737](https://github.com/ZoneMinder/ZoneMinder/pull/737) ([knnniggett](https://github.com/knnniggett))
@ -205,8 +228,6 @@
- Check to make sure that skin and css are valid. [\#713](https://github.com/ZoneMinder/ZoneMinder/pull/713) ([connortechnology](https://github.com/connortechnology)) - Check to make sure that skin and css are valid. [\#713](https://github.com/ZoneMinder/ZoneMinder/pull/713) ([connortechnology](https://github.com/connortechnology))
- Fixes \#710 Added libavformat version check around free context functions [\#711](https://github.com/ZoneMinder/ZoneMinder/pull/711) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Fixes \#710 Added libavformat version check around free context functions [\#711](https://github.com/ZoneMinder/ZoneMinder/pull/711) ([SteveGilvarry](https://github.com/SteveGilvarry))
- try harder to find arp. [\#709](https://github.com/ZoneMinder/ZoneMinder/pull/709) ([connortechnology](https://github.com/connortechnology)) - try harder to find arp. [\#709](https://github.com/ZoneMinder/ZoneMinder/pull/709) ([connortechnology](https://github.com/connortechnology))
- Merging Video and feature-h264-videostorage update [\#707](https://github.com/ZoneMinder/ZoneMinder/pull/707) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Update Version.txt to 1.28.1 [\#706](https://github.com/ZoneMinder/ZoneMinder/pull/706) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Make el6 and el7 build process a little more automated [\#704](https://github.com/ZoneMinder/ZoneMinder/pull/704) ([clipo1979](https://github.com/clipo1979)) - Make el6 and el7 build process a little more automated [\#704](https://github.com/ZoneMinder/ZoneMinder/pull/704) ([clipo1979](https://github.com/clipo1979))
- small improvements: [\#702](https://github.com/ZoneMinder/ZoneMinder/pull/702) ([connortechnology](https://github.com/connortechnology)) - small improvements: [\#702](https://github.com/ZoneMinder/ZoneMinder/pull/702) ([connortechnology](https://github.com/connortechnology))
- Centos 7 rpm packaging [\#700](https://github.com/ZoneMinder/ZoneMinder/pull/700) ([knnniggett](https://github.com/knnniggett)) - Centos 7 rpm packaging [\#700](https://github.com/ZoneMinder/ZoneMinder/pull/700) ([knnniggett](https://github.com/knnniggett))
@ -217,76 +238,6 @@
## [v1.28.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.28.1) (2015-02-05) ## [v1.28.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.28.1) (2015-02-05)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.28.0...v1.28.1) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.28.0...v1.28.1)
**Implemented enhancements:**
- Implement unit testing [\#266](https://github.com/ZoneMinder/ZoneMinder/issues/266)
- Replace PHP short tags [\#11](https://github.com/ZoneMinder/ZoneMinder/issues/11)
**Fixed bugs:**
- Streaming an Event as MPEG fails. [\#686](https://github.com/ZoneMinder/ZoneMinder/issues/686)
- Zoneminder Web UI No Longer Refreshes After Change [\#534](https://github.com/ZoneMinder/ZoneMinder/issues/534)
- Monster log messages [\#491](https://github.com/ZoneMinder/ZoneMinder/issues/491)
- zmu fails silently when it cannot read zm.conf [\#339](https://github.com/ZoneMinder/ZoneMinder/issues/339)
- Errors on Monitors page during first view [\#175](https://github.com/ZoneMinder/ZoneMinder/issues/175)
- Logs screen overflows when too much text in message column [\#138](https://github.com/ZoneMinder/ZoneMinder/issues/138)
- When filtering in the Events view, filter options are lost between pages [\#25](https://github.com/ZoneMinder/ZoneMinder/issues/25)
**Closed issues:**
- Gentoo Systemd ZM V1.28.0- New old bug with PATH\_SOCK and PATH\_SWAP [\#681](https://github.com/ZoneMinder/ZoneMinder/issues/681)
- PDO\_MYSQL the only PHP driver needed? [\#679](https://github.com/ZoneMinder/ZoneMinder/issues/679)
- Unable to probe local cameras, status is '127' [\#673](https://github.com/ZoneMinder/ZoneMinder/issues/673)
- zmc won't start automatically + Can't open memory map file [\#669](https://github.com/ZoneMinder/ZoneMinder/issues/669)
- Fake camera support [\#659](https://github.com/ZoneMinder/ZoneMinder/issues/659)
- Horrible error message when pressing probe [\#658](https://github.com/ZoneMinder/ZoneMinder/issues/658)
- socket\_sendto\( /var/run/zm/zms-256303s.sock \) failed: No such file or directory [\#656](https://github.com/ZoneMinder/ZoneMinder/issues/656)
- update feature should be removed or easily disabled [\#655](https://github.com/ZoneMinder/ZoneMinder/issues/655)
- zmfilter.pl crashes when processing background filter with no terms [\#652](https://github.com/ZoneMinder/ZoneMinder/issues/652)
- Use of undefined constants ZM\_SKIN\_DEFAULT and ZM\_CSS\_DEFAULT in index.php [\#650](https://github.com/ZoneMinder/ZoneMinder/issues/650)
- Improper track URL handling in zm\_rtsp.cpp [\#644](https://github.com/ZoneMinder/ZoneMinder/issues/644)
- Cannot install on jessie when running systemd [\#642](https://github.com/ZoneMinder/ZoneMinder/issues/642)
- Version detection [\#626](https://github.com/ZoneMinder/ZoneMinder/issues/626)
- some trash in debian package [\#625](https://github.com/ZoneMinder/ZoneMinder/issues/625)
- signed integers awesome [\#624](https://github.com/ZoneMinder/ZoneMinder/issues/624)
- cmake does not honor SYSCONFDIR [\#623](https://github.com/ZoneMinder/ZoneMinder/issues/623)
- PTZ Control Icons have disappeared [\#622](https://github.com/ZoneMinder/ZoneMinder/issues/622)
- RTSP Improvements [\#612](https://github.com/ZoneMinder/ZoneMinder/issues/612)
- CCTV Camera to IP converter [\#603](https://github.com/ZoneMinder/ZoneMinder/issues/603)
- mjpg streamer installations on fedora 20 [\#600](https://github.com/ZoneMinder/ZoneMinder/issues/600)
- Changing the skin in the options SHOULD be permanent. [\#598](https://github.com/ZoneMinder/ZoneMinder/issues/598)
- Zoneminder requires SElinux disabled on RHEL & derivatives. [\#593](https://github.com/ZoneMinder/ZoneMinder/issues/593)
- Editing control settings on a monitor should probably try to kill any running zmcontrol [\#590](https://github.com/ZoneMinder/ZoneMinder/issues/590)
- 1.28 missing dependency on debian jessie [\#581](https://github.com/ZoneMinder/ZoneMinder/issues/581)
- LibVLC MJPEG stream slows down [\#571](https://github.com/ZoneMinder/ZoneMinder/issues/571)
- %EV% in EMAIL\_BODY in E-mail options send still video [\#569](https://github.com/ZoneMinder/ZoneMinder/issues/569)
- Add documentation for EMAIL\_BODY variables [\#568](https://github.com/ZoneMinder/ZoneMinder/issues/568)
- 3S PTZ [\#566](https://github.com/ZoneMinder/ZoneMinder/issues/566)
- Live view wrong socket name [\#563](https://github.com/ZoneMinder/ZoneMinder/issues/563)
- V4L1 Support removal? [\#558](https://github.com/ZoneMinder/ZoneMinder/issues/558)
- feature-h264-videostorage compile errors [\#553](https://github.com/ZoneMinder/ZoneMinder/issues/553)
- zmc -m 1 crashed, signal 6 [\#540](https://github.com/ZoneMinder/ZoneMinder/issues/540)
- Attempt to assign buffer from a NULL pointer [\#538](https://github.com/ZoneMinder/ZoneMinder/issues/538)
- Please recommend ffmpeg settings for best video quality [\#536](https://github.com/ZoneMinder/ZoneMinder/issues/536)
- Modect Mode\(Active\) - How to revert from alarm to idle [\#509](https://github.com/ZoneMinder/ZoneMinder/issues/509)
- Update v1.27.99.0. [\#503](https://github.com/ZoneMinder/ZoneMinder/issues/503)
- Docker Container Broken [\#498](https://github.com/ZoneMinder/ZoneMinder/issues/498)
- Nordmark IP camera [\#483](https://github.com/ZoneMinder/ZoneMinder/issues/483)
- Release v1.28.0 [\#467](https://github.com/ZoneMinder/ZoneMinder/issues/467)
- Let's make a new website [\#446](https://github.com/ZoneMinder/ZoneMinder/issues/446)
- Zoneminder, Onvif CPU and RTSP capture [\#431](https://github.com/ZoneMinder/ZoneMinder/issues/431)
- Right memory settings to capture 1080p cameras [\#425](https://github.com/ZoneMinder/ZoneMinder/issues/425)
- Startup problem on Ubuntu [\#424](https://github.com/ZoneMinder/ZoneMinder/issues/424)
- Feature Request: Support for digest authentication over RTSP [\#399](https://github.com/ZoneMinder/ZoneMinder/issues/399)
- Install Zm V1.27.0 on Linux Gentoo x64 \(systemd\) [\#396](https://github.com/ZoneMinder/ZoneMinder/issues/396)
- Missing Dependencies [\#368](https://github.com/ZoneMinder/ZoneMinder/issues/368)
- Error "AVOutputFormat does not name a type AVOutputFormat \*of;" [\#340](https://github.com/ZoneMinder/ZoneMinder/issues/340)
- Add the ability to force RTSP over TCP in ffmpeg cameras. [\#323](https://github.com/ZoneMinder/ZoneMinder/issues/323)
- limited maximum path length for the device path prevents use of some by-id names [\#301](https://github.com/ZoneMinder/ZoneMinder/issues/301)
- Stream acquired via RTSP/FFMPEG won't recover from connection loss - "Unable to read packet from stream 0" [\#299](https://github.com/ZoneMinder/ZoneMinder/issues/299)
- Invalid response status 501: Method Not Implemented [\#298](https://github.com/ZoneMinder/ZoneMinder/issues/298)
- Invalid SOS parameters for sequential JPEG [\#279](https://github.com/ZoneMinder/ZoneMinder/issues/279)
**Merged pull requests:** **Merged pull requests:**
- fix content-type parsing when there are options on it [\#692](https://github.com/ZoneMinder/ZoneMinder/pull/692) ([connortechnology](https://github.com/connortechnology)) - fix content-type parsing when there are options on it [\#692](https://github.com/ZoneMinder/ZoneMinder/pull/692) ([connortechnology](https://github.com/connortechnology))
@ -315,11 +266,8 @@
- Output to stderror when zmu can't read zm.conf [\#627](https://github.com/ZoneMinder/ZoneMinder/pull/627) ([knnniggett](https://github.com/knnniggett)) - Output to stderror when zmu can't read zm.conf [\#627](https://github.com/ZoneMinder/ZoneMinder/pull/627) ([knnniggett](https://github.com/knnniggett))
- Add missing dependency to policykit-1 [\#621](https://github.com/ZoneMinder/ZoneMinder/pull/621) ([manupap1](https://github.com/manupap1)) - Add missing dependency to policykit-1 [\#621](https://github.com/ZoneMinder/ZoneMinder/pull/621) ([manupap1](https://github.com/manupap1))
- Replace PHP Short Open Tags - Fixes \#11 [\#620](https://github.com/ZoneMinder/ZoneMinder/pull/620) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Replace PHP Short Open Tags - Fixes \#11 [\#620](https://github.com/ZoneMinder/ZoneMinder/pull/620) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Video Highlander [\#618](https://github.com/ZoneMinder/ZoneMinder/pull/618) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Merge Master to feature-h264-videostorage [\#616](https://github.com/ZoneMinder/ZoneMinder/pull/616) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Rtsp [\#615](https://github.com/ZoneMinder/ZoneMinder/pull/615) ([knnniggett](https://github.com/knnniggett)) - Rtsp [\#615](https://github.com/ZoneMinder/ZoneMinder/pull/615) ([knnniggett](https://github.com/knnniggett))
- Merge flat css to classic [\#614](https://github.com/ZoneMinder/ZoneMinder/pull/614) ([connortechnology](https://github.com/connortechnology)) - Merge flat css to classic [\#614](https://github.com/ZoneMinder/ZoneMinder/pull/614) ([connortechnology](https://github.com/connortechnology))
- feature-h264-videostorage mp4 container [\#613](https://github.com/ZoneMinder/ZoneMinder/pull/613) ([SteveGilvarry](https://github.com/SteveGilvarry))
- echo the URL to the RTSP device during the OPTIONS directive [\#608](https://github.com/ZoneMinder/ZoneMinder/pull/608) ([knnniggett](https://github.com/knnniggett)) - echo the URL to the RTSP device during the OPTIONS directive [\#608](https://github.com/ZoneMinder/ZoneMinder/pull/608) ([knnniggett](https://github.com/knnniggett))
- Fix some memory leaks in zma [\#607](https://github.com/ZoneMinder/ZoneMinder/pull/607) ([manupap1](https://github.com/manupap1)) - Fix some memory leaks in zma [\#607](https://github.com/ZoneMinder/ZoneMinder/pull/607) ([manupap1](https://github.com/manupap1))
- Fix a mismatched free in zmc binary [\#606](https://github.com/ZoneMinder/ZoneMinder/pull/606) ([manupap1](https://github.com/manupap1)) - Fix a mismatched free in zmc binary [\#606](https://github.com/ZoneMinder/ZoneMinder/pull/606) ([manupap1](https://github.com/manupap1))
@ -346,91 +294,16 @@
- Fixed bug in rtsp streaming caused by a bad string concatenation [\#557](https://github.com/ZoneMinder/ZoneMinder/pull/557) ([manupap1](https://github.com/manupap1)) - Fixed bug in rtsp streaming caused by a bad string concatenation [\#557](https://github.com/ZoneMinder/ZoneMinder/pull/557) ([manupap1](https://github.com/manupap1))
- Add a stringVector join function for future use [\#556](https://github.com/ZoneMinder/ZoneMinder/pull/556) ([connortechnology](https://github.com/connortechnology)) - Add a stringVector join function for future use [\#556](https://github.com/ZoneMinder/ZoneMinder/pull/556) ([connortechnology](https://github.com/connortechnology))
- Fixed bug in rtsp streaming caused by a signed - unsigned conversion. [\#555](https://github.com/ZoneMinder/ZoneMinder/pull/555) ([manupap1](https://github.com/manupap1)) - Fixed bug in rtsp streaming caused by a signed - unsigned conversion. [\#555](https://github.com/ZoneMinder/ZoneMinder/pull/555) ([manupap1](https://github.com/manupap1))
- Keeping branch current, and fixing libvlc compile issues [\#554](https://github.com/ZoneMinder/ZoneMinder/pull/554) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Bumped version being found by zmupdate.pl [\#551](https://github.com/ZoneMinder/ZoneMinder/pull/551) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Update Ubuntu install instructions [\#550](https://github.com/ZoneMinder/ZoneMinder/pull/550) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Update Ubuntu install instructions [\#550](https://github.com/ZoneMinder/ZoneMinder/pull/550) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Ignore more files and initial travis framework [\#544](https://github.com/ZoneMinder/ZoneMinder/pull/544) ([kylejohnson](https://github.com/kylejohnson)) - Ignore more files and initial travis framework [\#544](https://github.com/ZoneMinder/ZoneMinder/pull/544) ([kylejohnson](https://github.com/kylejohnson))
- Update Travis to ffmpeg 2.4.2 [\#539](https://github.com/ZoneMinder/ZoneMinder/pull/539) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Update Travis to ffmpeg 2.4.2 [\#539](https://github.com/ZoneMinder/ZoneMinder/pull/539) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Add libvlc to Travis [\#535](https://github.com/ZoneMinder/ZoneMinder/pull/535) ([knnniggett](https://github.com/knnniggett)) - Add libvlc to Travis [\#535](https://github.com/ZoneMinder/ZoneMinder/pull/535) ([knnniggett](https://github.com/knnniggett))
- Merge master to feature-h264-videostorage and restore web GUI [\#532](https://github.com/ZoneMinder/ZoneMinder/pull/532) ([SteveGilvarry](https://github.com/SteveGilvarry))
- 351-Rebase Attempt for ffmpeg stability fixes [\#531](https://github.com/ZoneMinder/ZoneMinder/pull/531) ([SteveGilvarry](https://github.com/SteveGilvarry)) - 351-Rebase Attempt for ffmpeg stability fixes [\#531](https://github.com/ZoneMinder/ZoneMinder/pull/531) ([SteveGilvarry](https://github.com/SteveGilvarry))
- 478 Basic ONVIF Support [\#479](https://github.com/ZoneMinder/ZoneMinder/pull/479) ([altaroca](https://github.com/altaroca))
## [v1.28.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.28.0) (2014-10-18) ## [v1.28.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.28.0) (2014-10-18)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.27.0...v1.28.0) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.27.0...v1.28.0)
**Implemented enhancements:**
- Migrate completely to C++ [\#265](https://github.com/ZoneMinder/ZoneMinder/issues/265)
- All of the Config table shouldn't be written in Configure::write [\#192](https://github.com/ZoneMinder/ZoneMinder/issues/192)
- Translation stuff done, please pull in and test... [\#72](https://github.com/ZoneMinder/ZoneMinder/issues/72)
**Fixed bugs:**
- zms crashes due to monitor not running. [\#468](https://github.com/ZoneMinder/ZoneMinder/issues/468)
- Flat Skins Export Functions missing $ [\#455](https://github.com/ZoneMinder/ZoneMinder/issues/455)
- unexpected } in console.php [\#354](https://github.com/ZoneMinder/ZoneMinder/issues/354)
- incomplete path to arp in zoneminder/skins/classic/views/monitorprobe.php causes probe code 127 failures [\#271](https://github.com/ZoneMinder/ZoneMinder/issues/271)
- Minor errors when either OPT\_MAIL, OPT\_MESSAGE, or OPT\_UPLOAD are not set [\#34](https://github.com/ZoneMinder/ZoneMinder/issues/34)
**Closed issues:**
- Travis Build failing due to build issues with ffmpeg master [\#520](https://github.com/ZoneMinder/ZoneMinder/issues/520)
- 'zmfilter.pl' exited abnormally, exit status 9 [\#516](https://github.com/ZoneMinder/ZoneMinder/issues/516)
- Get the script on alarm feature working [\#515](https://github.com/ZoneMinder/ZoneMinder/issues/515)
- cmake installation on Arch Linux creates extraneous lib/perl5/... and share/man/... directories [\#514](https://github.com/ZoneMinder/ZoneMinder/issues/514)
- ZM Gui Stopped SU Syntax Error [\#512](https://github.com/ZoneMinder/ZoneMinder/issues/512)
- Error using log filter [\#504](https://github.com/ZoneMinder/ZoneMinder/issues/504)
- fps drop in latest snapshot 1.27.99 [\#495](https://github.com/ZoneMinder/ZoneMinder/issues/495)
- mysql missing field error after update [\#494](https://github.com/ZoneMinder/ZoneMinder/issues/494)
- Emails not including video when I add %EV% [\#487](https://github.com/ZoneMinder/ZoneMinder/issues/487)
- Cameras don't show remotely [\#484](https://github.com/ZoneMinder/ZoneMinder/issues/484)
- ZM Gui Stopped SU Syntax Error [\#482](https://github.com/ZoneMinder/ZoneMinder/issues/482)
- Airlink101 AIC500 mjpeg stream [\#481](https://github.com/ZoneMinder/ZoneMinder/issues/481)
- When a monitor's size is changed, the zone does not resize with it. [\#477](https://github.com/ZoneMinder/ZoneMinder/issues/477)
- .. [\#472](https://github.com/ZoneMinder/ZoneMinder/issues/472)
- Just A Note When Compiling [\#471](https://github.com/ZoneMinder/ZoneMinder/issues/471)
- firefox on windows not load all monitors in montage view [\#470](https://github.com/ZoneMinder/ZoneMinder/issues/470)
- Default to FLAT Skin [\#466](https://github.com/ZoneMinder/ZoneMinder/issues/466)
- zmlinkcontent.sh chown and chmod on symlink instead of content directory [\#463](https://github.com/ZoneMinder/ZoneMinder/issues/463)
- Cannot compile Zoneminder on CentOS 6.4 [\#461](https://github.com/ZoneMinder/ZoneMinder/issues/461)
- Video is not attached to e-mail anymore \(zm 1.27\) [\#460](https://github.com/ZoneMinder/ZoneMinder/issues/460)
- \[Video Branch\] Unknown column 'SaveJPEGs' in 'field list' [\#453](https://github.com/ZoneMinder/ZoneMinder/issues/453)
- Log Ajax loading oldest to newest [\#450](https://github.com/ZoneMinder/ZoneMinder/issues/450)
- '@' in password of a remote camera makes things go wrong [\#443](https://github.com/ZoneMinder/ZoneMinder/issues/443)
- Current code segfaults [\#439](https://github.com/ZoneMinder/ZoneMinder/issues/439)
- Crashing under Arch Linux [\#437](https://github.com/ZoneMinder/ZoneMinder/issues/437)
- Email Montage view on schedule [\#436](https://github.com/ZoneMinder/ZoneMinder/issues/436)
- \[question\] vmware image for latest ZM [\#428](https://github.com/ZoneMinder/ZoneMinder/issues/428)
- Cannot Compile [\#423](https://github.com/ZoneMinder/ZoneMinder/issues/423)
- seg in nph-zms/loadEventData atoi [\#417](https://github.com/ZoneMinder/ZoneMinder/issues/417)
- ffmpeg problem [\#414](https://github.com/ZoneMinder/ZoneMinder/issues/414)
- Minor fixes \(?\) for zmtrigger and mobile skin [\#410](https://github.com/ZoneMinder/ZoneMinder/issues/410)
- Misleading Config Dump [\#402](https://github.com/ZoneMinder/ZoneMinder/issues/402)
- Call to undefined function fixdevices\(\) [\#401](https://github.com/ZoneMinder/ZoneMinder/issues/401)
- Option to execute arbitrary script for each event. \[$100 awarded\] [\#400](https://github.com/ZoneMinder/ZoneMinder/issues/400)
- Zoneminder without Analysation [\#398](https://github.com/ZoneMinder/ZoneMinder/issues/398)
- Viewing 31 monitors in montage [\#379](https://github.com/ZoneMinder/ZoneMinder/issues/379)
- flat theme usability / Layout issues [\#378](https://github.com/ZoneMinder/ZoneMinder/issues/378)
- Undefined index: filter in /usr/share/zoneminder/skins/zmc/views/filter.php [\#369](https://github.com/ZoneMinder/ZoneMinder/issues/369)
- docker install not working [\#366](https://github.com/ZoneMinder/ZoneMinder/issues/366)
- Events are not being reported to table on main index page [\#364](https://github.com/ZoneMinder/ZoneMinder/issues/364)
- PatternFly for design commanality and improved user experience [\#363](https://github.com/ZoneMinder/ZoneMinder/issues/363)
- Radio buttons rendering in events replay in flat skin [\#356](https://github.com/ZoneMinder/ZoneMinder/issues/356)
- Pick a git branching strategy [\#350](https://github.com/ZoneMinder/ZoneMinder/issues/350)
- Compile directive ZM\_CGIDIR is not interpreted correctly [\#347](https://github.com/ZoneMinder/ZoneMinder/issues/347)
- 736516 - FTBFS: zm\_image.cpp:2991:165: error: \_\_attribute\_\_\(\(\_\_target\_\_\("sse2"\)\)\) is invalid [\#345](https://github.com/ZoneMinder/ZoneMinder/issues/345)
- zmcamtool isn't installed [\#344](https://github.com/ZoneMinder/ZoneMinder/issues/344)
- Overload Frame Ignore Count has no function [\#337](https://github.com/ZoneMinder/ZoneMinder/issues/337)
- preclusive zones calculated twice [\#336](https://github.com/ZoneMinder/ZoneMinder/issues/336)
- Build issue - In function `matroska\_decode\_buffer' [\#335](https://github.com/ZoneMinder/ZoneMinder/issues/335)
- High Load with Low CPU usage [\#326](https://github.com/ZoneMinder/ZoneMinder/issues/326)
- AUTH\_TYPE=remote not working in 1.26.4 [\#324](https://github.com/ZoneMinder/ZoneMinder/issues/324)
- Filter / Purge And Delete not running [\#321](https://github.com/ZoneMinder/ZoneMinder/issues/321)
- /root/zoneminder\_1.26.4-1\_amd64.deb not created [\#260](https://github.com/ZoneMinder/ZoneMinder/issues/260)
- 721161 - depends on ffmpeg which is going away [\#100](https://github.com/ZoneMinder/ZoneMinder/issues/100)
- 694131 - FTBFS against libav 9 [\#98](https://github.com/ZoneMinder/ZoneMinder/issues/98)
- Request: Better API/Remote control [\#23](https://github.com/ZoneMinder/ZoneMinder/issues/23)
**Merged pull requests:** **Merged pull requests:**
- fixes ftbs with no ffmpeg support [\#530](https://github.com/ZoneMinder/ZoneMinder/pull/530) ([knnniggett](https://github.com/knnniggett)) - fixes ftbs with no ffmpeg support [\#530](https://github.com/ZoneMinder/ZoneMinder/pull/530) ([knnniggett](https://github.com/knnniggett))
@ -450,7 +323,6 @@
- Fixes errors when opening Filters \(issue \#34\) [\#457](https://github.com/ZoneMinder/ZoneMinder/pull/457) ([knnniggett](https://github.com/knnniggett)) - Fixes errors when opening Filters \(issue \#34\) [\#457](https://github.com/ZoneMinder/ZoneMinder/pull/457) ([knnniggett](https://github.com/knnniggett))
- Fixed missing $ on ARRAY\(event\[id\]\). Fixes \#455 [\#456](https://github.com/ZoneMinder/ZoneMinder/pull/456) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Fixed missing $ on ARRAY\(event\[id\]\). Fixes \#455 [\#456](https://github.com/ZoneMinder/ZoneMinder/pull/456) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Wrap sort order. Fixes \#450 [\#451](https://github.com/ZoneMinder/ZoneMinder/pull/451) ([SteveGilvarry](https://github.com/SteveGilvarry)) - Wrap sort order. Fixes \#450 [\#451](https://github.com/ZoneMinder/ZoneMinder/pull/451) ([SteveGilvarry](https://github.com/SteveGilvarry))
- Update downloads.html [\#448](https://github.com/ZoneMinder/ZoneMinder/pull/448) ([barjac](https://github.com/barjac))
- scripts: BusyBox compatibility [\#445](https://github.com/ZoneMinder/ZoneMinder/pull/445) ([clandmeter](https://github.com/clandmeter)) - scripts: BusyBox compatibility [\#445](https://github.com/ZoneMinder/ZoneMinder/pull/445) ([clandmeter](https://github.com/clandmeter))
- Fixed issue DateTime handling in filter queries that broke timeline view... [\#442](https://github.com/ZoneMinder/ZoneMinder/pull/442) ([Tim-Craig](https://github.com/Tim-Craig)) - Fixed issue DateTime handling in filter queries that broke timeline view... [\#442](https://github.com/ZoneMinder/ZoneMinder/pull/442) ([Tim-Craig](https://github.com/Tim-Craig))
- Cleaning up the Contribution section of the README [\#440](https://github.com/ZoneMinder/ZoneMinder/pull/440) ([kylejohnson](https://github.com/kylejohnson)) - Cleaning up the Contribution section of the README [\#440](https://github.com/ZoneMinder/ZoneMinder/pull/440) ([kylejohnson](https://github.com/kylejohnson))
@ -502,49 +374,8 @@
## [v1.27.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.27.0) (2014-03-15) ## [v1.27.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.27.0) (2014-03-15)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.5...v1.27.0) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.5...v1.27.0)
**Implemented enhancements:**
- Change help text of source "Maximum FPS" and "Alarm Maximum FPS" to note that this should only be used on analog cameras [\#273](https://github.com/ZoneMinder/ZoneMinder/issues/273)
- Make zmpkg.pl 'better' [\#272](https://github.com/ZoneMinder/ZoneMinder/issues/272)
- Enhance security by creating SELinux policies. [\#248](https://github.com/ZoneMinder/ZoneMinder/issues/248)
- Update wiki page \(please?\) [\#91](https://github.com/ZoneMinder/ZoneMinder/issues/91)
- Better ffmpeg Version Checking [\#31](https://github.com/ZoneMinder/ZoneMinder/issues/31)
- Proposed: Enable purgewhenfull filter by default [\#332](https://github.com/ZoneMinder/ZoneMinder/issues/332)
- Exportable Camera Configs [\#86](https://github.com/ZoneMinder/ZoneMinder/issues/86)
**Fixed bugs:**
- Vivotek cameras, ultra slow FPS. [\#204](https://github.com/ZoneMinder/ZoneMinder/issues/204)
- Script to remove auto-generated files [\#112](https://github.com/ZoneMinder/ZoneMinder/issues/112)
- zm\_mpeg no longer uses correct ffmpeg API's [\#83](https://github.com/ZoneMinder/ZoneMinder/issues/83)
- Not all options in Monitors/add.ctp are saved to the database [\#13](https://github.com/ZoneMinder/ZoneMinder/issues/13)
- Flat skin needs window widths fixed [\#331](https://github.com/ZoneMinder/ZoneMinder/issues/331)
- Configuration gets broken in database after crash [\#239](https://github.com/ZoneMinder/ZoneMinder/issues/239)
- zmc crashes after a few minutes of usage in 1.26.4 [\#237](https://github.com/ZoneMinder/ZoneMinder/issues/237)
**Closed issues:**
- Apache using private /tmp space [\#307](https://github.com/ZoneMinder/ZoneMinder/issues/307)
- zmtrigger.pl crashes, which keeps Monitors in alarm state. [\#295](https://github.com/ZoneMinder/ZoneMinder/issues/295)
- SQL-ERR using Timeline after executing Filter matching on string with whitespace [\#291](https://github.com/ZoneMinder/ZoneMinder/issues/291)
- zm\_signal.cpp crashing signal 11 \(Segmentation fault\) [\#288](https://github.com/ZoneMinder/ZoneMinder/issues/288)
- Zoneminder no longer builds when using -DZM\_NO\_FFMPEG=ON [\#285](https://github.com/ZoneMinder/ZoneMinder/issues/285)
- Can't to use chinese [\#278](https://github.com/ZoneMinder/ZoneMinder/issues/278)
- jquery is embedded inside export\_functions.php [\#274](https://github.com/ZoneMinder/ZoneMinder/issues/274)
- Implement live streaming of H264 camera streams [\#176](https://github.com/ZoneMinder/ZoneMinder/issues/176)
- Support non-embedded password challenge [\#33](https://github.com/ZoneMinder/ZoneMinder/issues/33)
- libvlc source type not working in Ubuntu 12.04.3 [\#330](https://github.com/ZoneMinder/ZoneMinder/issues/330)
- zmupdate.pl InnoDB conversion silent failure [\#320](https://github.com/ZoneMinder/ZoneMinder/issues/320)
- Release v1.27.0 \[$100 awarded\] [\#315](https://github.com/ZoneMinder/ZoneMinder/issues/315)
- Default skin is flat, can't switch to classic. ?skin doesn't help [\#313](https://github.com/ZoneMinder/ZoneMinder/issues/313)
- make failure [\#304](https://github.com/ZoneMinder/ZoneMinder/issues/304)
- Fix 'remote' AUTH\_TYPE [\#296](https://github.com/ZoneMinder/ZoneMinder/issues/296)
- Use libcurl for http\(s\) authentication with remote cameras \[$400 awarded\] [\#238](https://github.com/ZoneMinder/ZoneMinder/issues/238)
**Merged pull requests:** **Merged pull requests:**
- Release 1.27 [\#341](https://github.com/ZoneMinder/ZoneMinder/pull/341) ([kylejohnson](https://github.com/kylejohnson))
- Fix popup sizes in flat skins. Fixes \#331 [\#334](https://github.com/ZoneMinder/ZoneMinder/pull/334) ([kylejohnson](https://github.com/kylejohnson))
- zmcamtool.pl - import and export ptz camera controls & camera presets [\#318](https://github.com/ZoneMinder/ZoneMinder/pull/318) ([kylejohnson](https://github.com/kylejohnson)) - zmcamtool.pl - import and export ptz camera controls & camera presets [\#318](https://github.com/ZoneMinder/ZoneMinder/pull/318) ([kylejohnson](https://github.com/kylejohnson))
- Example script to react to monitor alarms [\#317](https://github.com/ZoneMinder/ZoneMinder/pull/317) ([kylejohnson](https://github.com/kylejohnson)) - Example script to react to monitor alarms [\#317](https://github.com/ZoneMinder/ZoneMinder/pull/317) ([kylejohnson](https://github.com/kylejohnson))
- Change comments for many Camera subclasses [\#316](https://github.com/ZoneMinder/ZoneMinder/pull/316) ([nereocystis](https://github.com/nereocystis)) - Change comments for many Camera subclasses [\#316](https://github.com/ZoneMinder/ZoneMinder/pull/316) ([nereocystis](https://github.com/nereocystis))
@ -572,34 +403,12 @@
## [v1.26.5](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.5) (2013-12-16) ## [v1.26.5](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.5) (2013-12-16)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.4...v1.26.5) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.4...v1.26.5)
**Implemented enhancements:**
- ZoneMinder domain / website / email [\#225](https://github.com/ZoneMinder/ZoneMinder/issues/225)
**Fixed bugs:**
- Post shmget problem due to \*code\* not shmmax/shmall [\#226](https://github.com/ZoneMinder/ZoneMinder/issues/226)
- SQL error when "pre event image count" \>150 or so due to insufficient ZM\_SQL\_LGE\_BUFSIZ [\#222](https://github.com/ZoneMinder/ZoneMinder/issues/222)
- 'asm' operand has impossible constraints [\#219](https://github.com/ZoneMinder/ZoneMinder/issues/219)
- ipv6 support [\#210](https://github.com/ZoneMinder/ZoneMinder/issues/210)
- RTSP decoding errors in 1.26.4 \[$450 awarded\] [\#221](https://github.com/ZoneMinder/ZoneMinder/issues/221)
- The Prev "\<+" button does not work [\#32](https://github.com/ZoneMinder/ZoneMinder/issues/32)
**Closed issues:**
- Strict subs error? [\#262](https://github.com/ZoneMinder/ZoneMinder/issues/262)
- PHP depreciating [\#229](https://github.com/ZoneMinder/ZoneMinder/issues/229)
- Add a feature to monitor camera\(s\) availability [\#228](https://github.com/ZoneMinder/ZoneMinder/issues/228)
- Release 1.26.4 [\#202](https://github.com/ZoneMinder/ZoneMinder/issues/202)
- 631969 - 2 problems with options screen [\#106](https://github.com/ZoneMinder/ZoneMinder/issues/106)
- 657620 - Path issues for js scripts [\#102](https://github.com/ZoneMinder/ZoneMinder/issues/102)
- Support http digest authentication for IP camera access [\#30](https://github.com/ZoneMinder/ZoneMinder/issues/30)
**Merged pull requests:** **Merged pull requests:**
- Add reference to zm\_update-1.26.5.sql in Makefile.am [\#269](https://github.com/ZoneMinder/ZoneMinder/pull/269) ([knnniggett](https://github.com/knnniggett)) - Add reference to zm\_update-1.26.5.sql in Makefile.am [\#269](https://github.com/ZoneMinder/ZoneMinder/pull/269) ([knnniggett](https://github.com/knnniggett))
- Detection Support for WansView Cams [\#268](https://github.com/ZoneMinder/ZoneMinder/pull/268) ([Phhere](https://github.com/Phhere)) - Detection Support for WansView Cams [\#268](https://github.com/ZoneMinder/ZoneMinder/pull/268) ([Phhere](https://github.com/Phhere))
- use proper DBI parameter passing to improve security [\#264](https://github.com/ZoneMinder/ZoneMinder/pull/264) ([connortechnology](https://github.com/connortechnology)) - use proper DBI parameter passing to improve security [\#264](https://github.com/ZoneMinder/ZoneMinder/pull/264) ([connortechnology](https://github.com/connortechnology))
- Fix RTSP decoding errors in 1.26.4 \(addresses \#221\) [\#259](https://github.com/ZoneMinder/ZoneMinder/pull/259) ([ebarnard](https://github.com/ebarnard))
- Network Detection Support for Wansview [\#257](https://github.com/ZoneMinder/ZoneMinder/pull/257) ([Phhere](https://github.com/Phhere)) - Network Detection Support for Wansview [\#257](https://github.com/ZoneMinder/ZoneMinder/pull/257) ([Phhere](https://github.com/Phhere))
- Fix checkJsonError messages [\#256](https://github.com/ZoneMinder/ZoneMinder/pull/256) ([Phhere](https://github.com/Phhere)) - Fix checkJsonError messages [\#256](https://github.com/ZoneMinder/ZoneMinder/pull/256) ([Phhere](https://github.com/Phhere))
- Update README.md [\#255](https://github.com/ZoneMinder/ZoneMinder/pull/255) ([zdanek](https://github.com/zdanek)) - Update README.md [\#255](https://github.com/ZoneMinder/ZoneMinder/pull/255) ([zdanek](https://github.com/zdanek))
@ -608,16 +417,9 @@
- Fix shared memory errors on centos 6.4 [\#250](https://github.com/ZoneMinder/ZoneMinder/pull/250) ([insidenothing](https://github.com/insidenothing)) - Fix shared memory errors on centos 6.4 [\#250](https://github.com/ZoneMinder/ZoneMinder/pull/250) ([insidenothing](https://github.com/insidenothing))
- Update zoneminder.service [\#246](https://github.com/ZoneMinder/ZoneMinder/pull/246) ([dtmf](https://github.com/dtmf)) - Update zoneminder.service [\#246](https://github.com/ZoneMinder/ZoneMinder/pull/246) ([dtmf](https://github.com/dtmf))
- remove extra stuff that I don't think we need because we are the source. Opinions? [\#240](https://github.com/ZoneMinder/ZoneMinder/pull/240) ([connortechnology](https://github.com/connortechnology)) - remove extra stuff that I don't think we need because we are the source. Opinions? [\#240](https://github.com/ZoneMinder/ZoneMinder/pull/240) ([connortechnology](https://github.com/connortechnology))
- Re-Add ZM\_PATH\_DATA [\#236](https://github.com/ZoneMinder/ZoneMinder/pull/236) ([knnniggett](https://github.com/knnniggett))
- Cast content\_length to signed int for error-check comparison [\#232](https://github.com/ZoneMinder/ZoneMinder/pull/232) ([josephevans](https://github.com/josephevans)) - Cast content\_length to signed int for error-check comparison [\#232](https://github.com/ZoneMinder/ZoneMinder/pull/232) ([josephevans](https://github.com/josephevans))
- Apply INSERTs in Event::AddFrames in batches to fix issue \#222 [\#223](https://github.com/ZoneMinder/ZoneMinder/pull/223) ([fastolfe](https://github.com/fastolfe)) - Apply INSERTs in Event::AddFrames in batches to fix issue \#222 [\#223](https://github.com/ZoneMinder/ZoneMinder/pull/223) ([fastolfe](https://github.com/fastolfe))
- Updates to the zones view and edit pages [\#220](https://github.com/ZoneMinder/ZoneMinder/pull/220) ([kylejohnson](https://github.com/kylejohnson))
- ffmpeg detection improvements [\#218](https://github.com/ZoneMinder/ZoneMinder/pull/218) ([mastertheknife](https://github.com/mastertheknife)) - ffmpeg detection improvements [\#218](https://github.com/ZoneMinder/ZoneMinder/pull/218) ([mastertheknife](https://github.com/mastertheknife))
- cmake support files for redhat/centos distros [\#217](https://github.com/ZoneMinder/ZoneMinder/pull/217) ([knnniggett](https://github.com/knnniggett))
- Create ZM\_TARGET\_DISTRO [\#216](https://github.com/ZoneMinder/ZoneMinder/pull/216) ([knnniggett](https://github.com/knnniggett))
- We need a toggle for x10 support [\#215](https://github.com/ZoneMinder/ZoneMinder/pull/215) ([knnniggett](https://github.com/knnniggett))
- Cmake support files for fedora distro [\#214](https://github.com/ZoneMinder/ZoneMinder/pull/214) ([knnniggett](https://github.com/knnniggett))
- Initial zone editing in html5 canvas [\#213](https://github.com/ZoneMinder/ZoneMinder/pull/213) ([kylejohnson](https://github.com/kylejohnson))
- ZoneMinder Dutch Translation updates by Alco \(a.k. nightcrawler\) [\#211](https://github.com/ZoneMinder/ZoneMinder/pull/211) ([kylejohnson](https://github.com/kylejohnson)) - ZoneMinder Dutch Translation updates by Alco \(a.k. nightcrawler\) [\#211](https://github.com/ZoneMinder/ZoneMinder/pull/211) ([kylejohnson](https://github.com/kylejohnson))
- Change Prev Button functionality [\#207](https://github.com/ZoneMinder/ZoneMinder/pull/207) ([knnniggett](https://github.com/knnniggett)) - Change Prev Button functionality [\#207](https://github.com/ZoneMinder/ZoneMinder/pull/207) ([knnniggett](https://github.com/knnniggett))
- Delete PATH\_BUILD and TIME\_BUILD from zm.conf and fix ZM\_DB\_TYPE [\#243](https://github.com/ZoneMinder/ZoneMinder/pull/243) ([mastertheknife](https://github.com/mastertheknife)) - Delete PATH\_BUILD and TIME\_BUILD from zm.conf and fix ZM\_DB\_TYPE [\#243](https://github.com/ZoneMinder/ZoneMinder/pull/243) ([mastertheknife](https://github.com/mastertheknife))
@ -628,42 +430,6 @@
## [v1.26.4](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.4) (2013-10-08) ## [v1.26.4](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.4) (2013-10-08)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.3...v1.26.4) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.3...v1.26.4)
**Implemented enhancements:**
- Configuration options should be handled in the model, not the controller [\#191](https://github.com/ZoneMinder/ZoneMinder/issues/191)
- Travis CI automatic building [\#168](https://github.com/ZoneMinder/ZoneMinder/issues/168)
- Switch h264 feature branch to track the modern branch [\#167](https://github.com/ZoneMinder/ZoneMinder/issues/167)
- Add redhat specific files to source tree [\#115](https://github.com/ZoneMinder/ZoneMinder/issues/115)
- Performing count\(\) in SQL is slower than in PHP [\#2](https://github.com/ZoneMinder/ZoneMinder/issues/2)
**Fixed bugs:**
- New WebUI displays horizontal scroll bar with 100% width [\#169](https://github.com/ZoneMinder/ZoneMinder/issues/169)
- syntax error, unexpected $end on line 16 in LiveStreamHelper.php [\#147](https://github.com/ZoneMinder/ZoneMinder/issues/147)
- Readme.fedora contains incorrect references [\#145](https://github.com/ZoneMinder/ZoneMinder/issues/145)
- Bandwidth cookie issues [\#143](https://github.com/ZoneMinder/ZoneMinder/issues/143)
- Monitor image invalid when monitor not enabled [\#140](https://github.com/ZoneMinder/ZoneMinder/issues/140)
- Monitor image size too small [\#139](https://github.com/ZoneMinder/ZoneMinder/issues/139)
**Closed issues:**
- MJPEG without cambozola.jar on modern browsers \(including Linux ones\) [\#198](https://github.com/ZoneMinder/ZoneMinder/issues/198)
- Ability to hide all 'controls' and menus [\#171](https://github.com/ZoneMinder/ZoneMinder/issues/171)
- strace on zma gives "timer\_gettime...\(..\).. = -1 EINVAL \(Invalid argument\)" [\#170](https://github.com/ZoneMinder/ZoneMinder/issues/170)
- Add ability to zms \(or use the segmenter\) to play back h264 video either directly or transcoded [\#166](https://github.com/ZoneMinder/ZoneMinder/issues/166)
- I can delete multiple events at once. [\#137](https://github.com/ZoneMinder/ZoneMinder/issues/137)
- I can view logs [\#135](https://github.com/ZoneMinder/ZoneMinder/issues/135)
- I can update system config / options [\#134](https://github.com/ZoneMinder/ZoneMinder/issues/134)
- I can change the order of monitors [\#132](https://github.com/ZoneMinder/ZoneMinder/issues/132)
- When a new version is available, I am alerted [\#130](https://github.com/ZoneMinder/ZoneMinder/issues/130)
- Bandwidth is updated on the UI after chaning it [\#129](https://github.com/ZoneMinder/ZoneMinder/issues/129)
- I can change the bandwidth [\#128](https://github.com/ZoneMinder/ZoneMinder/issues/128)
- I can delete events [\#126](https://github.com/ZoneMinder/ZoneMinder/issues/126)
- I can view monitor streams individually [\#125](https://github.com/ZoneMinder/ZoneMinder/issues/125)
- 667428 - ftbfs with GCC-4.7 [\#99](https://github.com/ZoneMinder/ZoneMinder/issues/99)
- 707411 - FTBFS: zm\_local\_camera.cpp:742:49: error: invalid conversion from '\_\_u32 {aka unsigned int}' to 'v4l2\_buf\_type' [\#97](https://github.com/ZoneMinder/ZoneMinder/issues/97)
- Change in monitor setup requested. [\#19](https://github.com/ZoneMinder/ZoneMinder/issues/19)
**Merged pull requests:** **Merged pull requests:**
- Change frameserver warnings to debug level 2 [\#205](https://github.com/ZoneMinder/ZoneMinder/pull/205) ([knnniggett](https://github.com/knnniggett)) - Change frameserver warnings to debug level 2 [\#205](https://github.com/ZoneMinder/ZoneMinder/pull/205) ([knnniggett](https://github.com/knnniggett))
@ -671,26 +437,13 @@
- Signal improvements and fixes [\#201](https://github.com/ZoneMinder/ZoneMinder/pull/201) ([mastertheknife](https://github.com/mastertheknife)) - Signal improvements and fixes [\#201](https://github.com/ZoneMinder/ZoneMinder/pull/201) ([mastertheknife](https://github.com/mastertheknife))
- Create ZM\_PATH\_DATA and point zmupdate to ZM\_PATH\_DATA/db [\#200](https://github.com/ZoneMinder/ZoneMinder/pull/200) ([knnniggett](https://github.com/knnniggett)) - Create ZM\_PATH\_DATA and point zmupdate to ZM\_PATH\_DATA/db [\#200](https://github.com/ZoneMinder/ZoneMinder/pull/200) ([knnniggett](https://github.com/knnniggett))
- remove ${CMAKE\_CURRENT\_SOURCE\_DIR} from add\_custom\_target [\#199](https://github.com/ZoneMinder/ZoneMinder/pull/199) ([knnniggett](https://github.com/knnniggett)) - remove ${CMAKE\_CURRENT\_SOURCE\_DIR} from add\_custom\_target [\#199](https://github.com/ZoneMinder/ZoneMinder/pull/199) ([knnniggett](https://github.com/knnniggett))
- Updated cmake for the modern WebUI branch [\#196](https://github.com/ZoneMinder/ZoneMinder/pull/196) ([mastertheknife](https://github.com/mastertheknife))
- Added missing word in readme [\#194](https://github.com/ZoneMinder/ZoneMinder/pull/194) ([WDKevin](https://github.com/WDKevin)) - Added missing word in readme [\#194](https://github.com/ZoneMinder/ZoneMinder/pull/194) ([WDKevin](https://github.com/WDKevin))
- Moved writing of configure options from Controller to Model. Fixes \#191. [\#193](https://github.com/ZoneMinder/ZoneMinder/pull/193) ([kylejohnson](https://github.com/kylejohnson))
- Moved zmBandwidth option from cookie to Configure:: option. Might fix \#175 [\#190](https://github.com/ZoneMinder/ZoneMinder/pull/190) ([kylejohnson](https://github.com/kylejohnson))
- Moved the Config tabs to the sidebar [\#185](https://github.com/ZoneMinder/ZoneMinder/pull/185) ([kylejohnson](https://github.com/kylejohnson))
- Added datetime picker support and implemented on events sidebar [\#179](https://github.com/ZoneMinder/ZoneMinder/pull/179) ([WDKevin](https://github.com/WDKevin))
- Add cmake to ZoneMinder [\#178](https://github.com/ZoneMinder/ZoneMinder/pull/178) ([mastertheknife](https://github.com/mastertheknife)) - Add cmake to ZoneMinder [\#178](https://github.com/ZoneMinder/ZoneMinder/pull/178) ([mastertheknife](https://github.com/mastertheknife))
- Fixes the fixed-width container bug in bootstrap [\#177](https://github.com/ZoneMinder/ZoneMinder/pull/177) ([WDKevin](https://github.com/WDKevin))
- Rtsp updates [\#174](https://github.com/ZoneMinder/ZoneMinder/pull/174) ([POKKAHOH](https://github.com/POKKAHOH)) - Rtsp updates [\#174](https://github.com/ZoneMinder/ZoneMinder/pull/174) ([POKKAHOH](https://github.com/POKKAHOH))
- Minor patches to support older ffmpeg under distro's like Ubuntu 12.04 [\#173](https://github.com/ZoneMinder/ZoneMinder/pull/173) ([chetan-prime](https://github.com/chetan-prime))
- Solution for Issue \#170 [\#172](https://github.com/ZoneMinder/ZoneMinder/pull/172) ([raulcaj](https://github.com/raulcaj)) - Solution for Issue \#170 [\#172](https://github.com/ZoneMinder/ZoneMinder/pull/172) ([raulcaj](https://github.com/raulcaj))
- Fixing debian build files including automated database setup [\#164](https://github.com/ZoneMinder/ZoneMinder/pull/164) ([jaydio](https://github.com/jaydio)) - Fixing debian build files including automated database setup [\#164](https://github.com/ZoneMinder/ZoneMinder/pull/164) ([jaydio](https://github.com/jaydio))
- Add fedora rpm development files to zoneminder source tree [\#163](https://github.com/ZoneMinder/ZoneMinder/pull/163) ([knnniggett](https://github.com/knnniggett)) - Add fedora rpm development files to zoneminder source tree [\#163](https://github.com/ZoneMinder/ZoneMinder/pull/163) ([knnniggett](https://github.com/knnniggett))
- Improve Chrome browser support & log streaming events [\#162](https://github.com/ZoneMinder/ZoneMinder/pull/162) ([knnniggett](https://github.com/knnniggett)) - Improve Chrome browser support & log streaming events [\#162](https://github.com/ZoneMinder/ZoneMinder/pull/162) ([knnniggett](https://github.com/knnniggett))
- Merge master into modern to keep changes up to date [\#161](https://github.com/ZoneMinder/ZoneMinder/pull/161) ([chriswiggins](https://github.com/chriswiggins))
- Checks for updates every 5 minutes and notifies the user when there is one [\#158](https://github.com/ZoneMinder/ZoneMinder/pull/158) ([WDKevin](https://github.com/WDKevin))
- Dynamic monitor resizing [\#157](https://github.com/ZoneMinder/ZoneMinder/pull/157) ([chriswiggins](https://github.com/chriswiggins))
- Delete multiple events at once [\#156](https://github.com/ZoneMinder/ZoneMinder/pull/156) ([WDKevin](https://github.com/WDKevin))
- Added missing jquery-2.0.1.min.map file [\#155](https://github.com/ZoneMinder/ZoneMinder/pull/155) ([WDKevin](https://github.com/WDKevin))
- Add support to change order of monitors [\#154](https://github.com/ZoneMinder/ZoneMinder/pull/154) ([WDKevin](https://github.com/WDKevin))
- Can't seem to catch a break tonight. Moving debian files into correct folder [\#149](https://github.com/ZoneMinder/ZoneMinder/pull/149) ([knnniggett](https://github.com/knnniggett)) - Can't seem to catch a break tonight. Moving debian files into correct folder [\#149](https://github.com/ZoneMinder/ZoneMinder/pull/149) ([knnniggett](https://github.com/knnniggett))
- Move debian folder under distros [\#148](https://github.com/ZoneMinder/ZoneMinder/pull/148) ([knnniggett](https://github.com/knnniggett)) - Move debian folder under distros [\#148](https://github.com/ZoneMinder/ZoneMinder/pull/148) ([knnniggett](https://github.com/knnniggett))
- Removing the redhat folder from the root for real this time [\#141](https://github.com/ZoneMinder/ZoneMinder/pull/141) ([knnniggett](https://github.com/knnniggett)) - Removing the redhat folder from the root for real this time [\#141](https://github.com/ZoneMinder/ZoneMinder/pull/141) ([knnniggett](https://github.com/knnniggett))
@ -702,11 +455,6 @@
## [v1.26.3](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.3) (2013-09-10) ## [v1.26.3](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.3) (2013-09-10)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.2...v1.26.3) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.2...v1.26.3)
**Fixed bugs:**
- syntax error near unexpected token `5.6.0' [\#118](https://github.com/ZoneMinder/ZoneMinder/issues/118)
- Must modify zmupdate whenever the zm release number is incremented [\#114](https://github.com/ZoneMinder/ZoneMinder/issues/114)
**Merged pull requests:** **Merged pull requests:**
- Add 1.26.1 and 1.26.2 releases to zmupdate [\#116](https://github.com/ZoneMinder/ZoneMinder/pull/116) ([knnniggett](https://github.com/knnniggett)) - Add 1.26.1 and 1.26.2 releases to zmupdate [\#116](https://github.com/ZoneMinder/ZoneMinder/pull/116) ([knnniggett](https://github.com/knnniggett))
@ -714,19 +462,6 @@
## [v1.26.2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.2) (2013-09-06) ## [v1.26.2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.2) (2013-09-06)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.1...v1.26.2) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.1...v1.26.2)
**Implemented enhancements:**
- Update zmupdate to look at the github repo for the latest version [\#109](https://github.com/ZoneMinder/ZoneMinder/issues/109)
**Fixed bugs:**
- 666980 - hash authentication broken in update [\#105](https://github.com/ZoneMinder/ZoneMinder/issues/105)
**Closed issues:**
- 1.26.1 didn't get bumped from 1.26.0 [\#113](https://github.com/ZoneMinder/ZoneMinder/issues/113)
- Migrate FAQ from ZoneMinder Wiki to GitHub Wiki [\#110](https://github.com/ZoneMinder/ZoneMinder/issues/110)
**Merged pull requests:** **Merged pull requests:**
- Use GitHub repo for version check [\#111](https://github.com/ZoneMinder/ZoneMinder/pull/111) ([chriswiggins](https://github.com/chriswiggins)) - Use GitHub repo for version check [\#111](https://github.com/ZoneMinder/ZoneMinder/pull/111) ([chriswiggins](https://github.com/chriswiggins))
@ -734,85 +469,18 @@
## [v1.26.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.1) (2013-09-06) ## [v1.26.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.1) (2013-09-06)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.0...v1.26.1) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26.0...v1.26.1)
**Fixed bugs:**
- Make and configure files are not in v1.26.0 [\#107](https://github.com/ZoneMinder/ZoneMinder/issues/107)
## [v1.26.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.0) (2013-09-05) ## [v1.26.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26.0) (2013-09-05)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.3...v1.26.0) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.3...v1.26.0)
**Closed issues:**
- AM is deprecated in automake-1.13 onwards [\#94](https://github.com/ZoneMinder/ZoneMinder/issues/94)
- CVE-2013-0232 [\#93](https://github.com/ZoneMinder/ZoneMinder/issues/93)
- \[CRITICAL\] zms crashes with hashed authentication [\#88](https://github.com/ZoneMinder/ZoneMinder/issues/88)
**Merged pull requests:**
- Fix "Can't stat : No such file or directory" message [\#95](https://github.com/ZoneMinder/ZoneMinder/pull/95) ([knnniggett](https://github.com/knnniggett))
- Update getBrowser\(\) to match IE10 [\#92](https://github.com/ZoneMinder/ZoneMinder/pull/92) ([knnniggett](https://github.com/knnniggett))
- Update zmupdate.pl.in to give option to convert to InnoDB tables [\#84](https://github.com/ZoneMinder/ZoneMinder/pull/84) ([knnniggett](https://github.com/knnniggett))
## [v1.26-beta.3](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.3) (2013-08-28) ## [v1.26-beta.3](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.3) (2013-08-28)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.2...v1.26-beta.3) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.2...v1.26-beta.3)
**Fixed bugs:**
- libjpeg turbo errors during make [\#52](https://github.com/ZoneMinder/ZoneMinder/issues/52)
**Closed issues:**
- configure.ac checking for libavcore incorrectly [\#64](https://github.com/ZoneMinder/ZoneMinder/issues/64)
**Merged pull requests:**
- Fix for Issue \#88 - ZMS crashing [\#90](https://github.com/ZoneMinder/ZoneMinder/pull/90) ([knnniggett](https://github.com/knnniggett))
- Fixed typo [\#89](https://github.com/ZoneMinder/ZoneMinder/pull/89) ([knnniggett](https://github.com/knnniggett))
- edit zmupdate function in init script [\#87](https://github.com/ZoneMinder/ZoneMinder/pull/87) ([knnniggett](https://github.com/knnniggett))
- Add PTZ control files and camera presets for specific ptz cameras. [\#85](https://github.com/ZoneMinder/ZoneMinder/pull/85) ([knnniggett](https://github.com/knnniggett))
- Update Makefile.am [\#81](https://github.com/ZoneMinder/ZoneMinder/pull/81) ([knnniggett](https://github.com/knnniggett))
- Suppresses erroneous Corrupt Jpeg messages sent from the jpeg library [\#80](https://github.com/ZoneMinder/ZoneMinder/pull/80) ([knnniggett](https://github.com/knnniggett))
- Added frameserver patch from Zoneminder Wiki [\#79](https://github.com/ZoneMinder/ZoneMinder/pull/79) ([knnniggett](https://github.com/knnniggett))
- Don't check for gnutls-openssl on systems with older gnutls [\#78](https://github.com/ZoneMinder/ZoneMinder/pull/78) ([knnniggett](https://github.com/knnniggett))
- Change default dB Engine from MyISAM to InnoDB [\#77](https://github.com/ZoneMinder/ZoneMinder/pull/77) ([knnniggett](https://github.com/knnniggett))
- Added build notes for CentOS & RHEL [\#76](https://github.com/ZoneMinder/ZoneMinder/pull/76) ([knnniggett](https://github.com/knnniggett))
## [v1.26-beta.2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.2) (2013-08-15) ## [v1.26-beta.2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.2) (2013-08-15)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.1...v1.26-beta.2) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.26-beta.1...v1.26-beta.2)
**Implemented enhancements:**
- Updated Hungarian translation [\#35](https://github.com/ZoneMinder/ZoneMinder/issues/35)
**Fixed bugs:**
- 1.26 Beta does not install SkyIPCam7xx.pm Control Script [\#38](https://github.com/ZoneMinder/ZoneMinder/issues/38)
**Closed issues:**
- Store video in a \*video\* format [\#40](https://github.com/ZoneMinder/ZoneMinder/issues/40)
**Merged pull requests:**
- Update hu\_hu.php [\#37](https://github.com/ZoneMinder/ZoneMinder/pull/37) ([nagyrobi](https://github.com/nagyrobi))
## [v1.26-beta.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.1) (2013-08-13) ## [v1.26-beta.1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.26-beta.1) (2013-08-13)
[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.25...v1.26-beta.1) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.25...v1.26-beta.1)
**Implemented enhancements:**
- Scripts should only be loaded on the pages they're needed [\#15](https://github.com/ZoneMinder/ZoneMinder/issues/15)
**Fixed bugs:**
- Control Types always none using source Ffmpeg [\#16](https://github.com/ZoneMinder/ZoneMinder/issues/16)
- No PTZ control option when adding a new monitor [\#4](https://github.com/ZoneMinder/ZoneMinder/issues/4)
- Monitors/index.ctp Undefined offset error [\#1](https://github.com/ZoneMinder/ZoneMinder/issues/1)
**Closed issues:**
- Please Add my code for 0-23Hour 0n/off Zone Operation [\#24](https://github.com/ZoneMinder/ZoneMinder/issues/24)
## [v1.25](https://github.com/ZoneMinder/ZoneMinder/tree/v1.25) (2013-04-12) ## [v1.25](https://github.com/ZoneMinder/ZoneMinder/tree/v1.25) (2013-04-12)

View File

@ -4,7 +4,7 @@
# #
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
project (zoneminder) project (zoneminder)
set(zoneminder_VERSION "1.28.109") set(zoneminder_VERSION "1.29.0")
# make API version a minor of ZM version # make API version a minor of ZM version
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1") set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")

View File

@ -3,7 +3,7 @@
# For instructions on building with cmake, please see INSTALL # For instructions on building with cmake, please see INSTALL
# #
AC_PREREQ(2.59) AC_PREREQ(2.59)
AC_INIT(zm,1.28.109,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html) AC_INIT(zm,1.29.0,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR(src/zm.h) AC_CONFIG_SRCDIR(src/zm.h)
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)

View File

@ -269,6 +269,7 @@ DROP TABLE IF EXISTS `Logs`;
CREATE TABLE `Logs` ( CREATE TABLE `Logs` (
`TimeKey` decimal(16,6) NOT NULL, `TimeKey` decimal(16,6) NOT NULL,
`Component` varchar(32) NOT NULL, `Component` varchar(32) NOT NULL,
`ServerId` int(10) unsigned,
`Pid` smallint(6) DEFAULT NULL, `Pid` smallint(6) DEFAULT NULL,
`Level` tinyint(3) NOT NULL, `Level` tinyint(3) NOT NULL,
`Code` char(3) NOT NULL, `Code` char(3) NOT NULL,
@ -412,6 +413,7 @@ INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');
DROP TABLE IF EXISTS `Servers`; DROP TABLE IF EXISTS `Servers`;
CREATE TABLE `Servers` ( CREATE TABLE `Servers` (
`Id` int(10) unsigned NOT NULL auto_increment, `Id` int(10) unsigned NOT NULL auto_increment,
`Hostname` TEXT,
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`State_Id` int(10) unsigned, `State_Id` int(10) unsigned,
PRIMARY KEY (`Id`) PRIMARY KEY (`Id`)

21
db/zm_update-1.28.110.sql Normal file
View File

@ -0,0 +1,21 @@
--
-- This updates a 1.28.106 database to 1.28.107
--
--
-- Update Frame table to have a PrimaryKey of ID, insetad of a Composite Primary Key
-- Used primarially for compatibility with CakePHP
--
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Logs'
AND table_schema = DATABASE()
AND column_name = 'ServerId'
) > 0,
"SELECT 'Column ServerId already exists in Logs'",
"ALTER TABLE `Logs` ADD COLUMN `ServerId` int(10) unsigned AFTER Component"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

5
db/zm_update-1.29.0.sql Normal file
View File

@ -0,0 +1,5 @@
--
-- This updates a 1.28.110 database to 1.29.0
--
-- No changes required
--

View File

@ -1,3 +1,21 @@
zoneminder (1.28.108-nmu2015100101) wheezy; urgency=low
*
-- Isaac Connor <iconnor@connortechnology.com> Thu, 01 Oct 2015 18:20:29 +0000
zoneminder (1.28.107-nmu2015092401) wheezy; urgency=low
*
-- Isaac Connor <iconnor@connortechnology.com> Thu, 24 Sep 2015 14:15:46 +0000
zoneminder (1.28.1+106-nmu2015091001) wheezy; urgency=low
*
-- Isaac Connor <iconnor@connortechnology.com> Thu, 10 Sep 2015 18:03:43 +0000
zoneminder (1.28.0-0.1) wheezy; urgency=low zoneminder (1.28.0-0.1) wheezy; urgency=low
* Use CMake instead of Autotools to simplify * Use CMake instead of Autotools to simplify

View File

@ -3,5 +3,6 @@ usr/lib/zoneminder/cgi-bin
usr/share/man usr/share/man
usr/share/perl5/ZoneMinder usr/share/perl5/ZoneMinder
usr/share/perl5/ZoneMinder.pm usr/share/perl5/ZoneMinder.pm
usr/share/zoneminder usr/share/zoneminder/db
usr/share/zoneminder/www
etc/zm etc/zm

View File

@ -44,12 +44,10 @@ New installs
set during the previous step, you will need to create the ZoneMinder set during the previous step, you will need to create the ZoneMinder
database and configure a database account for ZoneMinder to use: database and configure a database account for ZoneMinder to use:
mysql -u root -p < /usr/share/zoneminder/db/zm_create.sql mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
mysql -u root -p mysql -uroot -p -e "grant all on zm.* to \
mysql> grant all 'zmuser'@localhost identified by 'zmpass';"
on zm.* to 'zmuser'@localhost identified by 'zmpass'; mysqladmin -uroot -p reload
mysql> exit;
mysqladmin -u root -p reload
The database account credentials, zmuser/zmpass, are arbitrary. Set them to The database account credentials, zmuser/zmpass, are arbitrary. Set them to
anything that suits your envinroment. anything that suits your envinroment.
@ -125,9 +123,7 @@ Upgrades
have increased. Verify the zmuser database account has been granted all have increased. Verify the zmuser database account has been granted all
permission to the ZoneMinder database: permission to the ZoneMinder database:
mysql -u root -p mysql -uroot -p -e "show grants for zmuser@localhost;"
mysql> show grants for zmuser@localhost;
mysql> exit;
See step 2 of the Installation section to add missing permissions. See step 2 of the Installation section to add missing permissions.

View File

@ -10,7 +10,7 @@
%define _without_x10 1 %define _without_x10 1
Name: zoneminder Name: zoneminder
Version: 1.28.1 Version: 1.29.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
@ -65,7 +65,7 @@ too much degradation of performance.
%setup -q -n ZoneMinder-%{version} %setup -q -n ZoneMinder-%{version}
# Change the following default values # Change the following default values
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms ./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes ./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm ./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload ./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload
@ -138,7 +138,7 @@ fi
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/jscalendar-doc %doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/README.https distros/fedora/jscalendar-doc
%config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf %config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf
%config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf %config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf
%config(noreplace) /etc/tmpfiles.d/zoneminder.conf %config(noreplace) /etc/tmpfiles.d/zoneminder.conf

View File

@ -38,7 +38,7 @@ BuildRequires: gcc gcc-c++ vlc-devel libcurl-devel libv4l-devel
BuildRequires: httpd polkit-devel BuildRequires: httpd polkit-devel
%{!?_without_ffmpeg:BuildRequires: ffmpeg} %{!?_without_ffmpeg:BuildRequires: ffmpeg}
Requires: httpd php php-gd php-mysql cambozola polkit net-tools psmisc Requires: httpd php php-gd php-mysql cambozola polkit net-tools psmisc mod_ssl
Requires: libjpeg-turbo vlc-core libcurl Requires: libjpeg-turbo vlc-core libcurl
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip) Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip)
@ -65,7 +65,7 @@ too much degradation of performance.
%setup -q -n ZoneMinder-%{version} %setup -q -n ZoneMinder-%{version}
# Change the following default values # Change the following default values
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms ./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes ./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm ./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload ./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload
@ -138,7 +138,7 @@ fi
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/jscalendar-doc %doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/README.https distros/fedora/jscalendar-doc
%config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf %config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf
%config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf %config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf
%config(noreplace) /etc/tmpfiles.d/zoneminder.conf %config(noreplace) /etc/tmpfiles.d/zoneminder.conf

View File

@ -30,12 +30,9 @@ New installs
will need to create the ZoneMinder database and configure a database will need to create the ZoneMinder database and configure a database
account for ZoneMinder to use: account for ZoneMinder to use:
mysql -uroot -p
mysql> create database zm;
mysql> grant all
on zm.* to 'zmuser'@localhost identified by 'zmpass';
mysql> exit;
mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
mysql -uroot -p -e "grant all on zm.* to \
'zmuser'@localhost identified by 'zmpass';"
mysqladmin -uroot -p reload mysqladmin -uroot -p reload
The database account credentials, zmuser/zmpass, are arbitrary. Set them to The database account credentials, zmuser/zmpass, are arbitrary. Set them to
@ -117,9 +114,7 @@ New installs
have increased. Verify the zmuser database account has been granted all have increased. Verify the zmuser database account has been granted all
permission to the ZoneMinder database: permission to the ZoneMinder database:
mysql -u root -p mysql -uroot -p -e "show grants for zmuser@localhost;"
mysql> show grants for zmuser@localhost;
mysql> exit;
See step 2 of the Installation section to add missing permissions. See step 2 of the Installation section to add missing permissions.

View File

@ -32,12 +32,10 @@ New installs
will need to create the ZoneMinder database and configure a database will need to create the ZoneMinder database and configure a database
account for ZoneMinder to use: account for ZoneMinder to use:
mysql -u root -p < /usr/share/zoneminder/db/zm_create.sql mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
mysql -u root -p mysql -uroot -p -e "grant all on zm.* to \
mysql> grant all 'zmuser'@localhost identified by 'zmpass';"
on zm.* to 'zmuser'@localhost identified by 'zmpass'; mysqladmin -uroot -p reload
mysql> exit;
mysqladmin -u root -p reload
The database account credentials, zmuser/zmpass, are arbitrary. Set them to The database account credentials, zmuser/zmpass, are arbitrary. Set them to
anything that suits your envinroment. anything that suits your envinroment.
@ -112,9 +110,7 @@ Upgrades
have increased. Verify the zmuser database account has been granted all have increased. Verify the zmuser database account has been granted all
permission to the ZoneMinder database: permission to the ZoneMinder database:
mysql -u root -p mysql -uroot -p -e "show grants for zmuser@localhost;"
mysql> show grants for zmuser@localhost;
mysql> exit;
See step 2 of the Installation section to add missing permissions. See step 2 of the Installation section to add missing permissions.

View File

@ -4,7 +4,7 @@
%define zmgid_final apache %define zmgid_final apache
Name: zoneminder Name: zoneminder
Version: 1.28.1 Version: 1.29.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
@ -130,7 +130,7 @@ rm -rf %{_docdir}/%{name}-%{version}
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.CentOS distros/redhat/jscalendar-doc %doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.CentOS distros/redhat/README.https distros/redhat/jscalendar-doc
%doc distros/redhat/local_zoneminder.te %doc distros/redhat/local_zoneminder.te
%config %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm.conf %config %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm.conf
%config(noreplace) %attr(644,root,root) %{_sysconfdir}/httpd/conf.d/zoneminder.conf %config(noreplace) %attr(644,root,root) %{_sysconfdir}/httpd/conf.d/zoneminder.conf

View File

@ -6,7 +6,7 @@
%global _hardened_build 1 %global _hardened_build 1
Name: zoneminder Name: zoneminder
Version: 1.28.1 Version: 1.29.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
@ -137,7 +137,7 @@ fi
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.Centos7 distros/redhat/jscalendar-doc %doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.Centos7 distros/redhat/README.https distros/redhat/jscalendar-doc
%doc distros/redhat/local_zoneminder.te %doc distros/redhat/local_zoneminder.te
%config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf %config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf
%config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf %config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf

View File

@ -104,7 +104,7 @@ Package: zoneminder-doc
Section: doc Section: doc
Architecture: all Architecture: all
Multi-Arch: foreign Multi-Arch: foreign
Depends: ${misc:Depends}, ${sphinxdoc:Depends} Depends: ${misc:Depends}, ${sphinxdoc:Depends}, python-sphinx-rtd-theme | python3-sphinx-rtd-theme
Suggests: www-browser Suggests: www-browser
Description: ZoneMinder documentation Description: ZoneMinder documentation
ZoneMinder is intended for use in single or multi-camera video security ZoneMinder is intended for use in single or multi-camera video security

View File

@ -1,10 +1,10 @@
/var/log/zm/*log { /var/log/zm/*.log {
missingok missingok
notifempty notifempty
sharedscripts sharedscripts
postrotate postrotate
/usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || : /usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || :
endscript endscript
weekly daily
rotate 3 rotate 7
} }

View File

@ -4,7 +4,8 @@
[Unit] [Unit]
Description=ZoneMinder CCTV recording and surveillance system Description=ZoneMinder CCTV recording and surveillance system
After=network.target mysql.service After=network.target mysql.service
Requires=mysql.service # Remarked out so that it will start ZM on machines that don't have mysql installed
#Requires=mysql.service
[Service] [Service]
#User=www-data #User=www-data

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1 @@
<mxfile type="dropbox" userAgent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0" version="5.2.7.3" editor="www.draw.io"><diagram>7Vvfb+I4F/1rkHYfFpEEQnlsmXZ2pXZUqaPd/fZlZIib+JsQs44pZf76uU6uEydOgELoUgkeELn+fc/JuddO6HnTxetnQZbRAw9o3HMHwWvP+9Rz3SvfhW9l2OSGsTfKDaFgQW5ySsMT+0HROEDrigU0rVSUnMeSLavGOU8SOpcVGxGCr6vVnnlcHXVJQj1iaXiak9i2/sUCGeGyXL+0/05ZGOmRHX+Sl8zI/Hso+CrB8Xqu95x98uIF0X1lC/VuwYeCc+hG/Vq8Tmms/Kh9lHvjrqW0mKSgCU5kRwMHUXgh8QpX+g9P6ANLAirA/rACF//2RMVLdvmFyjUX3+HXV77kMQ83PdePYaibGRT7ofqVd5jKjXZdtniqRnSgeB0xSZ+WZK5K18AVsEVyEWNxKgX/TqfQtwBLAnMB4zOL45op4oL94IkkuiFMUDLA6zpmYQI2yVXPz1AFyeRcFZMzHYQ+U80pkjUzocM+U76gUsA6B1jqISORyB52sC5ZMR5jlchgxFgzmSATw6LnEiD4gRi14OWOLbweSALkW6gF7cYC1qjsBzicoF/nMBBwwXb4ggWBGqYRYQ61n2O+BksE9Sg0MLFR0AguiWRcdeWCA2Fm0AVLQnVdXgHvwKCKVXM9R7ipBgPfn067gdgZDCsYu+MrC+QR3jkmxg7e88dBjJ0YEN+zBO65C7jdgKtRKsAd9xHLHfCimB4Fr2aSARsNINLgJRcy4iFPSHxbWsF7WkGVbwx8aRJcq+BWIgmWO8AXq/6fSrlBGMhKcgVWMcI9z9yt+ml1a8pXIoM6cxzGcElESLHeCAVJLWKr9wWNgQEv1XDa5MmsKayKqFa6wpKzRKZGz4/KYIhyTZUdDMwlKnmPza2dQa31EMO6Hj53A7aqgV2scS/8J+jDjvB/ZfJvZe57Pl7+L7scT/DykQoG01M3ddb4XRnjoYyeIWFGflXia4Sx6g8neOPuQ7ADeKHdYqj+n5DxcjDdX3+xOGNwwJRzkMpp9rG0H0r8qyvnxoOSUJCAAW61IKDNn5iADDoX60SBX3SmM99MsiOyVJNZvEK7ZdRP8tQw7c9WAMEhY9Q0H7Nk72ZpUFhl0zPoyqD1jbYha0GlMfyguxqy4jcHDb8qEOBMO+vTCV7XIWOEzDOo8SS5UBuWCznOkBzDyTuSowjKtnDk+WLAXnTCOI2Vd6HuL183S5Xd/dqUVOYWGNdoaVGsLT9r3oVp6z2Z0fiRpwzBnXEp+QIqxLWCIg+1EtMz5vZyfgJuOTVyTeztZpG9VLabnXALifzfJSswY7OJujbbqOt6o5NnMNrWXQazPyD23tBGyMrwUpi9rNnM+6h2RpJVN1LCaoLY6rad7jB3Vw2M1ba35X12Lj9sUeMdufzOjootoe4o50QXmwJfy8IWWNUZYnGihWac4D4CU5yMkpnusTxwbBKeSTU/9jT1TOFpCmqF8aiUp4nneWBS689Wo+Xd/3eljkuBmN7dnQcf05SHrzJd0ieZW8JePsAl7u0d99Lcp7VTHKXXO4JhQfvd0dBg3aSJdDoEHkM6HWm33YUGDPuBe1Mc/zdlr820afB9K7StZIhIkOm90uyApFERkes4Mp6O+wzUIe2rpyIZkkdhpbPi6oZ5bCfFQ/SviaQ+xznuCHUPPT3bMInuc8cYborwYztwWxjdP2LWRxpO8CzirRGzdcrdR0zd8xsDxGAwnSqpqAeITwTiIkntCGHFA2tTdcywb4hDl13ZUdHpW4opQPc7NHgKXM2U9La+skVrelqkjcdpnb3//3BaN3QgaWtKtTvXuvpIB+8OWqd8gt3B9kf0WrAuWrB/ptq1Bng+hsxCA2wCnyxvdVyk4keWgNGwnjucSgLqIx0sAa1T7l4C7IdDFwk4MwkYTqqvFbyzBOBpzUeWAP/ddjz1kQ7e8bROuXsJsB8CXiTgzCTAr78a+J4SoJ9KNOyIZ3rD+McjVJiSBRXE3nru91Cw6OtCtb2oNl8JJjff5rnTO3mBbTSqbj2KR8AGzTQTO3/crDu+vIB6yncUXa/+jqL99OVkL6DqN5ovL6CeCNyR9Xbx6V5Ahcvy7wR52lH+P8O7/Qk=</diagram></mxfile>

View File

@ -10,3 +10,4 @@ Contents:
debian debian
fedora fedora
centos centos
multiserver

View File

@ -0,0 +1,55 @@
Multi-Server Install
====================
It is possible to run multiple ZoneMinder servers and manage them from a single interface. To achieve this each zoneminder server is connected to a single shared database server and shares file storage for event data.
.. image:: images/zm-multiserver.png
Topology Design Notes
---------------------
1. Device symbols represent separate logical functions, not necessarily separate hardware. For example, the Database Server and a ZoneMinder Server, can reside on the same physical hardware.
2. Configure each ZoneMinder Server to use the same, remote Database Server (Green).
3. The Storage Server (Red) represents shared storage, accessible by all ZoneMinder Servers, mounted under each servers events folder.
4. Create at least two networks for best performance. Dedicate a Storage LAN for communication with the Storage and Database Servers. Make use of multipath and jumbo frames if possible. Keep all other traffic off the Storage LAN! Dedicate the second LAN, called the Video LAN in the diagram, for all other traffic.
New installs
------------
1. Follow the normal instructions for your distro for installing ZoneMinder onto all the ZoneMinder servers in the normal fashion. Only a single database will be needed either as standalone, or on one of the ZoneMinder Servers.
2. On each ZoneMinder server, edit zm.conf. Find the ZM_DB_HOST variable and set it to the name or ip address of your Database Server. Find the ZM_SERVER_HOST and enter a name for this ZoneMinder server. Use a name easily recognizable by you. This name is not used by ZoneMinder for dns or any other form of network conectivity.
3. Copy the file /usr/share/zoneminder/db/zm_create.sql from one of the ZoneMinder Servers to the machine targeted as the Database Server.
4. Install mysql/mariadb server onto the Database Server.
5. It is advised to run "mysql_secure_installation" to help secure the server.
6. Using the password for the root account set during the previous step, create the ZoneMinder database and configure a database account for ZoneMinder to use:
::
mysql -u root -p < zm_create.sql
mysql -uroot -p -e "grant all on zm.* to 'zmuser'@localhost identified by 'zmpass';"
mysqladmin -u root -p reload
The database account credentials, zmuser/zmpass, are arbitrary. Set them to anything that suits your environment.
Note that these commands are just an example and might not be secure enough for your environment.
7. If you have chosen to change the ZoneMinder database account credentials to something other than zmuser/zmpass, you must now update zm.conf on each ZoneMinder Server. Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
Additionally, you must also edit /usr/share/zoneminder/www/api/app/Config/database.php in a similar manner on each ZoneMinder Server. Scroll down and change login and password to the values you created in the previous step.
8. All ZoneMinders Servers must share a common events folder. This can be done in any manner supported by the underlying operating system. From the Storage Server, share/export a folder to be used for ZoneMinder events.
9. From each ZoneMinder Server, mount the shared events folder on the Storage Server to the events folder on the local ZoneMinder Server.
NOTE: The location of this folder varies by distro. This folder is often found under "/var/lib/zoneminder/events" for RedHat based distros and "/var/cache/zoneminder/events" for Debain based distros. This folder is NOT a Symbolic Link!
10. Open your browser and point it to the web console on any of the ZoneMinder Servers (they will all be the same). Open Options, click the Servers tab,and populate this screen with all of your ZoneMinder Servers. Each server has a field for its name and its hostname. The name is what you used for ZM_SERVER_HOST in step 2. The hostname is the network name or ip address ZoneMinder should use.
11. When creating a new Monitor, remember to select the server the camera will be assigned to from the Server drop down box.

View File

@ -21,6 +21,9 @@ Monitor Tab
Name Name
The name for your monitor. This should be made up of alphanumeric characters (a-z,A-Z,0-9) and hyphen (-) and underscore(_) only. Whitespace is not allowed. The name for your monitor. This should be made up of alphanumeric characters (a-z,A-Z,0-9) and hyphen (-) and underscore(_) only. Whitespace is not allowed.
Server
Multi-Server implementation allows the ability to define multiple ZoneMinder servers sharing a single database. When servers are configured this setting allows you nominate the server for each monitor.
Source Type Source Type
This determines whether the camera is a local one attached to a physical video or USB port on your machine, a remote network camera or an image source that is represented by a file (for instance periodically downloaded from a alternate location). Choosing one or the other affects which set of options are shown in the Source tab. This determines whether the camera is a local one attached to a physical video or USB port on your machine, a remote network camera or an image source that is represented by a file (for instance periodically downloaded from a alternate location). Choosing one or the other affects which set of options are shown in the Source tab.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,12 @@
Options - Servers
---------------
.. image:: images/Options_Servers.png
Servers tab is used for setting up multiple ZoneMinder servers sharing the same database and using a shared file share for all event data. To add a new server use the Add Server button. All that is required is a Name for the Server and Hostname.
To delete a server mark that server and click the Delete button.
Please note that all servers must have a functional web UI as the live view must come from the monitor's host server.
On each server, you will have to edit /etc/zm/zm.conf and set either ZM_SERVER_NAME=

View File

@ -102,6 +102,20 @@ BEGIN
} }
$sth->finish(); $sth->finish();
#$dbh->disconnect(); #$dbh->disconnect();
if ( ! exists $Config{ZM_SERVER_ID} ) {
$Config{ZM_SERVER_ID} = undef;
$sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' );
if ( $Config{ZM_SERVER_NAME} ) {
$res = $sth->execute( $Config{ZM_SERVER_NAME} );
my $result = $sth->fetchrow_hashref();
$Config{ZM_SERVER_ID} = $$result{Id};
} elsif ( $Config{ZM_SERVER_HOST} ) {
$res = $sth->execute( $Config{ZM_SERVER_HOST} );
my $result = $sth->fetchrow_hashref();
$Config{ZM_SERVER_ID} = $$result{Id};
}
}
} }
1; 1;

View File

@ -173,6 +173,7 @@ sub moveConDown
Debug( "Move Down" ); Debug( "Move Down" );
my $cmd = "decoder_control.cgi?command=2"; my $cmd = "decoder_control.cgi?command=2";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
$self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
} }
#Left Arrow #Left Arrow

View File

@ -0,0 +1,161 @@
# ==========================================================================
#
# ZoneMinder Server Module, $Date$, $Revision$
# Copyright (C) 2001-2008 Philip Coombes
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
#
# This module contains the common definitions and functions used by the rest
# of the ZoneMinder scripts
#
package ZoneMinder::Server;
use 5.006;
use strict;
use warnings;
require Exporter;
require ZoneMinder::Base;
our @ISA = qw(Exporter ZoneMinder::Base);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use ZoneMinder ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = (
'functions' => [ qw(
) ]
);
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# General Utility Functions
#
# ==========================================================================
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
use POSIX;
sub new {
my ( $parent, $id, $data ) = @_;
my $self = {};
bless $self, $parent;
if ( ( $$self{Id} = $id ) or $data ) {
#$log->debug("loading $parent $id") if $debug or DEBUG_ALL;
$self->load( $data );
}
return $self;
} # end sub new
sub load {
my ( $self, $data ) = @_;
my $type = ref $self;
if ( ! $data ) {
#$log->debug("Object::load Loading from db $type");
$data = $ZoneMinder::Database::dbh->selectrow_hashref( 'SELECT * FROM Servers WHERE Id=?', {}, $$self{Id} );
if ( ! $data ) {
if ( $ZoneMinder::Database::dbh->errstr ) {
Error( "Failure to load Server record for $$self{id}: Reason: " . $ZoneMinder::Database::dbh->errstr );
} # end if
} # end if
} # end if ! $data
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub load
sub Name {
if ( @_ > 1 ) {
$_[0]{Name} = $_[1];
}
return $_[0]{Name};
} # end sub Name
sub Hostname {
if ( @_ > 1 ) {
$_[0]{Hostname} = $_[1];
}
return $_[0]{Hostname};
} # end sub Hostname
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah
=head1 SYNOPSIS
use ZoneMinder::Server;
blah blah blah
=head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub
unedited.
Blah blah blah.
=head2 EXPORT
None by default.
=head1 SEE ALSO
Mention other useful documentation such as the documentation of
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.
If you have a mailing list set up for your module, mention it here.
If you have a web site set up for your module, mention it here.
=head1 AUTHOR
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2001-2008 Philip Coombes
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -178,6 +178,8 @@ MAIN: while( $loop ) {
my $fs_monitors; my $fs_monitors;
foreach my $monitor ( glob("[0-9]*") ) foreach my $monitor ( glob("[0-9]*") )
{ {
# Thie glob above gives all files starting with a digit. So a monitor with a name starting with a digit will be in this list.
next if $monitor =~ /\D/;
Debug( "Found filesystem monitor '$monitor'" ); Debug( "Found filesystem monitor '$monitor'" );
my $fs_events = $fs_monitors->{$monitor} = {}; my $fs_events = $fs_monitors->{$monitor} = {};
( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); # De-taint ( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); # De-taint

View File

@ -349,6 +349,10 @@ sub getFilters
my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/; my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/;
$db_filter->{Sql} .= "M.".$temp_attr_name; $db_filter->{Sql} .= "M.".$temp_attr_name;
} }
elsif ( $filter_expr->{terms}[$i]->{attr} eq 'ServerId' )
{
$db_filter->{Sql} .= "M.ServerId";
}
elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' )
{ {
$db_filter->{Sql} .= "E.StartTime"; $db_filter->{Sql} .= "E.StartTime";
@ -392,6 +396,13 @@ sub getFilters
{ {
$value = "'$temp_value'"; $value = "'$temp_value'";
} }
elsif ( $filter_expr->{terms}[$i]->{attr} eq 'ServerId' ) {
if ( $temp_value eq 'ZM_SERVER_ID' ) {
$value = "'$Config{ZM_SERVER_ID}'";
} else {
$value = "'$temp_value'";
}
}
elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name' elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name'
|| $filter_expr->{terms}[$i]->{attr} eq 'Cause' || $filter_expr->{terms}[$i]->{attr} eq 'Cause'
|| $filter_expr->{terms}[$i]->{attr} eq 'Notes' || $filter_expr->{terms}[$i]->{attr} eq 'Notes'

View File

@ -121,10 +121,10 @@ my $retval = 0;
if ( $command eq "state" ) if ( $command eq "state" )
{ {
Info( "Updating DB: $state->{Name}\n" ); Info( "Updating DB: $state->{Name}\n" );
my $sql = "select * from Monitors order by Id asc"; my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() )
{ {
@ -226,10 +226,11 @@ if ( $command =~ /^(?:start|restart)$/ )
zmMemTidy(); zmMemTidy();
runCommand( "zmdc.pl startup" ); runCommand( "zmdc.pl startup" );
my $sql = "select * from Monitors"; Info( "Starting up services" . ( $Config{ZM_SERVER_ID} ? " for server $Config{ZM_SERVER_ID}\n" : "\n" ) );
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() )
{ {

View File

@ -433,11 +433,12 @@ sub loadMonitors
my %new_monitors = (); my %new_monitors = ();
my $sql = "SELECT * FROM Monitors my $sql = "SELECT * FROM Monitors
WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )" WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )".
( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' )
; ;
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() )
{ {
@ -503,22 +504,11 @@ sub handleMessage
Info( "Set monitor to $state\n" ); Info( "Set monitor to $state\n" );
if ( $delay ) if ( $delay )
{ {
my $action_time = time()+$delay;
my $action_text = $id."|".( ($state eq "enable") my $action_text = $id."|".( ($state eq "enable")
? "disable" ? "disable"
: "enable" : "enable"
) );
; handleDelay($delay, $connection, $action_text);
my $action_array = $actions{$action_time};
if ( !$action_array )
{
$action_array = $actions{$action_time} = [];
}
push( @$action_array, { connection=>$connection,
message=>$action_text
}
);
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
} }
} }
elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ )
@ -533,43 +523,33 @@ sub handleMessage
zmTriggerEventOn( $monitor, $score, $cause, $text ); zmTriggerEventOn( $monitor, $score, $cause, $text );
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
Info( "Trigger '$trigger' '$cause'\n" ); Info( "Trigger '$trigger' '$cause'\n" );
if ( $delay )
{
my $action_text = $id."|cancel";
handleDelay($delay, $connection, $action_text);
}
} }
elsif ( $trigger eq "off" ) elsif ( $trigger eq "off" )
{ {
my $last_event = zmGetLastEvent( $monitor ); if ( $delay )
zmTriggerEventOff( $monitor );
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
Info( "Trigger '$trigger'\n" );
# Wait til it's finished
while( zmInAlarm( $monitor )
&& ($last_event == zmGetLastEvent( $monitor ))
)
{ {
# Tenth of a second my $action_text = $id."|off|0|".$cause."|".$text;
usleep( 100000 ); handleDelay($delay, $connection, $action_text);
} } else {
my $last_event = zmGetLastEvent( $monitor );
zmTriggerEventOff( $monitor );
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
Info( "Trigger '$trigger'\n" );
# Wait til it's finished
while( zmInAlarm( $monitor )
&& ($last_event == zmGetLastEvent( $monitor ))
)
{
# Tenth of a second
usleep( 100000 );
}
zmTriggerEventCancel( $monitor ); zmTriggerEventCancel( $monitor );
}
else
{
Info( "Trigger '$trigger'\n" );
zmTriggerEventCancel( $monitor );
}
if ( $delay )
{
my $action_time = time()+$delay;
#my $action_text = $id."|cancel|0|".$cause."|".$text;
my $action_text = $id."|cancel";
my $action_array = $actions{$action_time};
if ( !$action_array )
{
$action_array = $actions{$action_time} = [];
} }
push( @$action_array, { connection=>$connection,
message=>$action_text
}
);
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
} }
} }
elsif( $action eq "cancel" ) elsif( $action eq "cancel" )
@ -589,5 +569,23 @@ sub handleMessage
} }
} # end sub handleMessage } # end sub handleMessage
sub handleDelay
{
my $delay = shift;
my $connection = shift;
my $action_text = shift;
my $action_time = time()+$delay;
my $action_array = $actions{$action_time};
if ( !$action_array )
{
$action_array = $actions{$action_time} = [];
}
push( @$action_array, { connection=>$connection,
message=>$action_text
}
);
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
}
1; 1;
__END__ __END__

View File

@ -74,14 +74,14 @@ sleep( START_DELAY );
my $dbh = zmDbConnect(); my $dbh = zmDbConnect();
my $sql = "select * from Monitors"; my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
while( 1 ) while( 1 )
{ {
my $now = time(); my $now = time();
my $res = $sth->execute() my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() )
{ {

View File

@ -25,6 +25,8 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "zm_utils.h"
void zmLoadConfig() void zmLoadConfig()
{ {
FILE *cfg; FILE *cfg;
@ -91,17 +93,53 @@ void zmLoadConfig()
staticConfig.DB_PASS = std::string(val_ptr); staticConfig.DB_PASS = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 ) else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 )
staticConfig.PATH_WEB = std::string(val_ptr); staticConfig.PATH_WEB = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_SERVER_HOST" ) == 0 )
staticConfig.SERVER_NAME = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_SERVER_NAME" ) == 0 )
staticConfig.SERVER_NAME = std::string(val_ptr);
else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 )
staticConfig.SERVER_ID = atoi(val_ptr);
else else
{ {
// We ignore this now as there may be more parameters than the // We ignore this now as there may be more parameters than the
// c/c++ binaries are bothered about // c/c++ binaries are bothered about
// Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG ); // Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG );
} }
} } // end foreach line of the config
fclose( cfg); fclose( cfg );
zmDbConnect(); zmDbConnect();
config.Load(); config.Load();
config.Assign(); config.Assign();
// Populate the server config entries
if ( ! staticConfig.SERVER_ID ) {
if ( ! staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_ID = atoi(dbrow[0]);
} else {
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() );
}
} // end if has SERVER_NAME
} else if ( staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
}
}
if ( ! staticConfig.SERVER_ID ) {
Info( "No Server ID or Name specified in config. Not using Multi-Server Mode." );
} else {
Info( "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID );
}
} }
StaticConfig staticConfig; StaticConfig staticConfig;

View File

@ -65,6 +65,8 @@ struct StaticConfig
std::string DB_USER; std::string DB_USER;
std::string DB_PASS; std::string DB_PASS;
std::string PATH_WEB; std::string PATH_WEB;
std::string SERVER_NAME;
unsigned int SERVER_ID;
}; };
extern StaticConfig staticConfig; extern StaticConfig staticConfig;

View File

@ -95,7 +95,7 @@ MYSQL_RES * zmDbFetch( const char * query ) {
return result; return result;
} // end MYSQL_RES * zmDbFetch( const char * query ); } // end MYSQL_RES * zmDbFetch( const char * query );
MYSQL_ROW zmDBFetchOne( const char *query ) { MYSQL_ROW zmDbFetchOne( const char *query ) {
MYSQL_RES *result = zmDbFetch( query ); MYSQL_RES *result = zmDbFetch( query );
int n_rows = mysql_num_rows( result ); int n_rows = mysql_num_rows( result );
if ( n_rows != 1 ) { if ( n_rows != 1 ) {
@ -104,6 +104,7 @@ MYSQL_ROW zmDBFetchOne( const char *query ) {
} }
MYSQL_ROW dbrow = mysql_fetch_row( result ); MYSQL_ROW dbrow = mysql_fetch_row( result );
mysql_free_result( result );
if ( ! dbrow ) { if ( ! dbrow ) {
Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) ); Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) );
return NULL; return NULL;

View File

@ -33,7 +33,7 @@ void zmDbConnect();
void zmDbClose(); void zmDbClose();
MYSQL_RES * zmDbFetch( const char *query ); MYSQL_RES * zmDbFetch( const char *query );
MYSQL_ROW zmDBFetchOne( const char *query ); MYSQL_ROW zmDbFetchOne( const char *query );
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -1211,6 +1211,11 @@ void EventStream::processCommand( const CmdMsg *msg )
Debug( 1, "Got QUERY command, sending STATUS" ); Debug( 1, "Got QUERY command, sending STATUS" );
break; break;
} }
case CMD_QUIT :
{
Info ("User initiated exit - CMD_QUIT");
break;
}
default : default :
{ {
// Do nothing, for now // Do nothing, for now
@ -1248,6 +1253,9 @@ void EventStream::processCommand( const CmdMsg *msg )
exit( -1 ); exit( -1 );
} }
} }
// quit after sending a status, if this was a quit request
if ((MsgCommand)msg->msg_data[0]==CMD_QUIT)
exit(0);
updateFrameRate( (double)event_data->frame_count/event_data->duration ); updateFrameRate( (double)event_data->frame_count/event_data->duration );
} }

View File

@ -603,7 +603,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
char escapedString[(strlen(syslogStart)*2)+1]; char escapedString[(strlen(syslogStart)*2)+1];
mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) ); mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) );
snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), tid, level, classString, escapedString, file, line );
snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line );
if ( mysql_query( &mDbConnection, sql ) ) if ( mysql_query( &mDbConnection, sql ) )
{ {
databaseLevel( NOLOG ); databaseLevel( NOLOG );

View File

@ -270,6 +270,7 @@ bool Monitor::MonitorLink::hasAlarmed()
Monitor::Monitor( Monitor::Monitor(
int p_id, int p_id,
const char *p_name, const char *p_name,
const unsigned int p_server_id,
int p_function, int p_function,
bool p_enabled, bool p_enabled,
const char *p_linked_monitors, const char *p_linked_monitors,
@ -306,6 +307,7 @@ Monitor::Monitor(
int p_n_zones, int p_n_zones,
Zone *p_zones[] Zone *p_zones[]
) : id( p_id ), ) : id( p_id ),
server_id( p_server_id ),
function( (Function)p_function ), function( (Function)p_function ),
enabled( p_enabled ), enabled( p_enabled ),
width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ),
@ -2082,25 +2084,20 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors )
#if ZM_HAS_V4L #if ZM_HAS_V4L
int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose )
{ {
static char sql[ZM_SQL_MED_BUFSIZ]; std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'";
if ( !device[0] ) if ( device[0] ) {
{ sql += " AND Device='";
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); sql += device;
sql += "'";
} }
else if ( staticConfig.SERVER_ID ) {
{ sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
}
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
} }
Debug( 1, "Loading Local Monitors with %s", sql.c_str() );
MYSQL_RES *result = mysql_store_result( &dbconn ); MYSQL_RES *result = zmDbFetch( sql.c_str() );
if ( !result ) if ( !result ) {
{ Error( "Can't load local monitors: %s", mysql_error( &dbconn ) );
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
int n_monitors = mysql_num_rows( result ); int n_monitors = mysql_num_rows( result );
@ -2113,6 +2110,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
int id = atoi(dbrow[col]); col++; int id = atoi(dbrow[col]); col++;
const char *name = dbrow[col]; col++; const char *name = dbrow[col]; col++;
unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
int function = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++;
int enabled = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++;
const char *linked_monitors = dbrow[col]; col++; const char *linked_monitors = dbrow[col]; col++;
@ -2217,6 +2215,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
monitors[i] = new Monitor( monitors[i] = new Monitor(
id, id,
name, name,
server_id,
function, function,
enabled, enabled,
linked_monitors, linked_monitors,
@ -2273,24 +2272,18 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose )
{ {
static char sql[ZM_SQL_MED_BUFSIZ]; std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'";
if ( !protocol ) if ( staticConfig.SERVER_ID ) {
{ sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
}
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
} }
MYSQL_RES *result = mysql_store_result( &dbconn ); if ( protocol ) {
if ( !result ) sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
{ }
Debug( 1, "Loading Remote Monitors with %s", sql.c_str() );
MYSQL_RES *result = zmDbFetch( sql.c_str() );
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
@ -2304,6 +2297,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
int id = atoi(dbrow[col]); col++; int id = atoi(dbrow[col]); col++;
std::string name = dbrow[col]; col++; std::string name = dbrow[col]; col++;
unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
int function = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++;
int enabled = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++;
const char *linked_monitors = dbrow[col]; col++; const char *linked_monitors = dbrow[col]; col++;
@ -2407,6 +2401,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
monitors[i] = new Monitor( monitors[i] = new Monitor(
id, id,
name.c_str(), name.c_str(),
server_id,
function, function,
enabled, enabled,
linked_monitors, linked_monitors,
@ -2463,22 +2458,17 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose )
{ {
static char sql[ZM_SQL_MED_BUFSIZ]; std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'";
if ( !file[0] ) if ( file[0] ) {
{ sql += " AND Path='";
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); sql += file;
sql += "'";
} }
else if ( staticConfig.SERVER_ID ) {
{ sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file );
} }
if ( mysql_query( &dbconn, sql ) ) Debug( 1, "Loading File Monitors with %s", sql.c_str() );
{ MYSQL_RES *result = zmDbFetch( sql.c_str() );
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result ) if ( !result )
{ {
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
@ -2494,6 +2484,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
int id = atoi(dbrow[col]); col++; int id = atoi(dbrow[col]); col++;
const char *name = dbrow[col]; col++; const char *name = dbrow[col]; col++;
unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
int function = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++;
int enabled = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++;
const char *linked_monitors = dbrow[col]; col++; const char *linked_monitors = dbrow[col]; col++;
@ -2561,6 +2552,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
monitors[i] = new Monitor( monitors[i] = new Monitor(
id, id,
name, name,
server_id,
function, function,
enabled, enabled,
linked_monitors, linked_monitors,
@ -2617,27 +2609,22 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
#if HAVE_LIBAVFORMAT #if HAVE_LIBAVFORMAT
int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose )
{ {
static char sql[ZM_SQL_MED_BUFSIZ]; std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'";
if ( !file[0] ) if ( file[0] ) {
{ sql += " AND Path = '";
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) ); sql += file;
sql += "'";
} }
else if ( staticConfig.SERVER_ID ) {
{ sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
} }
if ( mysql_query( &dbconn, sql ) ) Debug( 1, "Loading FFMPEG Monitors with %s", sql.c_str() );
{ MYSQL_RES *result = zmDbFetch( sql.c_str() );
Error( "Can't run query: %s", mysql_error( &dbconn ) ); if ( ! result ) {
Error( "Cannot load FfmpegMonitors" );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int n_monitors = mysql_num_rows( result ); int n_monitors = mysql_num_rows( result );
Debug( 1, "Got %d monitors", n_monitors ); Debug( 1, "Got %d monitors", n_monitors );
delete[] monitors; delete[] monitors;
@ -2648,6 +2635,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
int id = atoi(dbrow[col]); col++; int id = atoi(dbrow[col]); col++;
const char *name = dbrow[col]; col++; const char *name = dbrow[col]; col++;
unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
int function = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++;
int enabled = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++;
const char *linked_monitors = dbrow[col]; col++; const char *linked_monitors = dbrow[col]; col++;
@ -2719,6 +2707,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
monitors[i] = new Monitor( monitors[i] = new Monitor(
id, id,
name, name,
server_id,
function, function,
enabled, enabled,
linked_monitors, linked_monitors,
@ -2773,338 +2762,320 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
} }
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT
Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose )
{ {
static char sql[ZM_SQL_MED_BUFSIZ]; std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", id );
if ( mysql_query( &dbconn, sql ) )
{
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn ); MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() );
if ( !result ) if ( ! dbrow ) {
{
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
int n_monitors = mysql_num_rows( result );
Debug( 1, "Got %d monitors", n_monitors );
Monitor *monitor = 0; Monitor *monitor = 0;
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) unsigned int col = 0;
{
int col = 0;
int id = atoi(dbrow[col]); col++; unsigned int id = atoi(dbrow[col]); col++;
std::string name = dbrow[col]; col++; std::string name = dbrow[col]; col++;
std::string type = dbrow[col]; col++; unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
int function = atoi(dbrow[col]); col++; std::string type = dbrow[col]; col++;
int enabled = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++;
std::string linked_monitors = dbrow[col]; col++; int enabled = atoi(dbrow[col]); col++;
std::string linked_monitors = dbrow[col]; col++;
std::string device = dbrow[col]; col++; std::string device = dbrow[col]; col++;
int channel = atoi(dbrow[col]); col++; int channel = atoi(dbrow[col]); col++;
int format = atoi(dbrow[col]); col++; int format = atoi(dbrow[col]); col++;
bool v4l_multi_buffer = config.v4l_multi_buffer; bool v4l_multi_buffer = config.v4l_multi_buffer;
if ( dbrow[col] ) { if ( dbrow[col] ) {
if (*dbrow[col] == '0' ) { if (*dbrow[col] == '0' ) {
v4l_multi_buffer = false; v4l_multi_buffer = false;
} else if ( *dbrow[col] == '1' ) { } else if ( *dbrow[col] == '1' ) {
v4l_multi_buffer = true; v4l_multi_buffer = true;
}
} }
col++; }
col++;
int v4l_captures_per_frame = 0; int v4l_captures_per_frame = 0;
if ( dbrow[col] ) { if ( dbrow[col] ) {
v4l_captures_per_frame = atoi(dbrow[col]); v4l_captures_per_frame = atoi(dbrow[col]);
} else { } else {
v4l_captures_per_frame = config.captures_per_frame; v4l_captures_per_frame = config.captures_per_frame;
} }
Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
col++; col++;
std::string protocol = dbrow[col]; col++; std::string protocol = dbrow[col]; col++;
std::string method = dbrow[col]; col++; std::string method = dbrow[col]; col++;
std::string host = dbrow[col]; col++; std::string host = dbrow[col]; col++;
std::string port = dbrow[col]; col++; std::string port = dbrow[col]; col++;
std::string path = dbrow[col]; col++; std::string path = dbrow[col]; col++;
std::string options = dbrow[col]; col++; std::string options = dbrow[col]; col++;
std::string user = dbrow[col]; col++; std::string user = dbrow[col]; col++;
std::string pass = dbrow[col]; col++; std::string pass = dbrow[col]; col++;
int width = atoi(dbrow[col]); col++; int width = atoi(dbrow[col]); col++;
int height = atoi(dbrow[col]); col++; int height = atoi(dbrow[col]); col++;
int colours = atoi(dbrow[col]); col++; int colours = atoi(dbrow[col]); col++;
int palette = atoi(dbrow[col]); col++; int palette = atoi(dbrow[col]); col++;
Orientation orientation = (Orientation)atoi(dbrow[col]); col++; Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
unsigned int deinterlacing = atoi(dbrow[col]); col++; unsigned int deinterlacing = atoi(dbrow[col]); col++;
bool rtsp_describe = (*dbrow[col] != '0'); col++; bool rtsp_describe = (*dbrow[col] != '0'); col++;
int savejpegs = atoi(dbrow[col]); col++; int savejpegs = atoi(dbrow[col]); col++;
int videowriter = atoi(dbrow[col]); col++; int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++; std::string encoderparams = dbrow[col]; col++;
int brightness = atoi(dbrow[col]); col++; int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++; int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++; int hue = atoi(dbrow[col]); col++;
int colour = atoi(dbrow[col]); col++; int colour = atoi(dbrow[col]); col++;
std::string event_prefix = dbrow[col]; col++; std::string event_prefix = dbrow[col]; col++;
std::string label_format = dbrow[col]; col++; std::string label_format = dbrow[col]; col++;
int label_x = atoi(dbrow[col]); col++; int label_x = atoi(dbrow[col]); col++;
int label_y = atoi(dbrow[col]); col++; int label_y = atoi(dbrow[col]); col++;
int label_size = atoi(dbrow[col]); col++; int label_size = atoi(dbrow[col]); col++;
int image_buffer_count = atoi(dbrow[col]); col++; int image_buffer_count = atoi(dbrow[col]); col++;
int warmup_count = atoi(dbrow[col]); col++; int warmup_count = atoi(dbrow[col]); col++;
int pre_event_count = atoi(dbrow[col]); col++; int pre_event_count = atoi(dbrow[col]); col++;
int post_event_count = atoi(dbrow[col]); col++; int post_event_count = atoi(dbrow[col]); col++;
int stream_replay_buffer = atoi(dbrow[col]); col++; int stream_replay_buffer = atoi(dbrow[col]); col++;
int alarm_frame_count = atoi(dbrow[col]); col++; int alarm_frame_count = atoi(dbrow[col]); col++;
int section_length = atoi(dbrow[col]); col++; int section_length = atoi(dbrow[col]); col++;
int frame_skip = atoi(dbrow[col]); col++; int frame_skip = atoi(dbrow[col]); col++;
int motion_frame_skip = atoi(dbrow[col]); col++; int motion_frame_skip = atoi(dbrow[col]); col++;
double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++;
unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0);
int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++;
int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++;
int fps_report_interval = atoi(dbrow[col]); col++; int fps_report_interval = atoi(dbrow[col]); col++;
int ref_blend_perc = atoi(dbrow[col]); col++; int ref_blend_perc = atoi(dbrow[col]); col++;
int alarm_ref_blend_perc = atoi(dbrow[col]); col++; int alarm_ref_blend_perc = atoi(dbrow[col]); col++;
int track_motion = atoi(dbrow[col]); col++; int track_motion = atoi(dbrow[col]); col++;
int signal_check_colour; int signal_check_colour;
if ( dbrow[col][0] == '#' ) if ( dbrow[col][0] == '#' )
signal_check_colour = strtol(dbrow[col]+1,0,16); signal_check_colour = strtol(dbrow[col]+1,0,16);
else else
signal_check_colour = strtol(dbrow[col],0,16); signal_check_colour = strtol(dbrow[col],0,16);
col++; col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
int extras = (deinterlacing>>24)&0xff; int extras = (deinterlacing>>24)&0xff;
Camera *camera = 0; Camera *camera = 0;
if ( type == "Local" ) if ( type == "Local" )
{
#if ZM_HAS_V4L
camera = new LocalCamera(
id,
device.c_str(),
channel,
format,
v4l_multi_buffer,
v4l_captures_per_frame,
method,
cam_width,
cam_height,
colours,
palette,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE,
extras
);
#else // ZM_HAS_V4L
Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id );
#endif // ZM_HAS_V4L
}
else if ( type == "Remote" )
{
if ( protocol == "http" )
{
camera = new RemoteCameraHttp(
id,
method.c_str(),
host.c_str(),
port.c_str(),
path.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
}
else if ( protocol == "rtsp" )
{
#if HAVE_LIBAVFORMAT
camera = new RemoteCameraRtsp(
id,
method.c_str(),
host.c_str(),
port.c_str(),
path.c_str(),
cam_width,
cam_height,
rtsp_describe,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBAVFORMAT
Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
#endif // HAVE_LIBAVFORMAT
}
else
{
Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
}
}
else if ( type == "File" )
{
camera = new FileCamera(
id,
path.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
}
else if ( type == "Ffmpeg" )
{
#if HAVE_LIBAVFORMAT
camera = new FfmpegCamera(
id,
path.c_str(),
method,
options,
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBAVFORMAT
Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id );
#endif // HAVE_LIBAVFORMAT
}
else if (type == "Libvlc")
{
#if HAVE_LIBVLC
camera = new LibvlcCamera(
id,
path.c_str(),
method,
options,
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBVLC
Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id );
#endif // HAVE_LIBVLC
}
else if ( type == "cURL" )
{
#if HAVE_LIBCURL
camera = new cURLCamera(
id,
path.c_str(),
user.c_str(),
pass.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBCURL
Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id );
#endif // HAVE_LIBCURL
}
else
{
Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id );
}
monitor = new Monitor(
id,
name.c_str(),
function,
enabled,
linked_monitors.c_str(),
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix.c_str(),
label_format.c_str(),
Coord( label_x, label_y ),
label_size,
image_buffer_count,
warmup_count,
pre_event_count,
post_event_count,
stream_replay_buffer,
alarm_frame_count,
section_length,
frame_skip,
motion_frame_skip,
analysis_fps,
analysis_update_delay,
capture_delay,
alarm_capture_delay,
fps_report_interval,
ref_blend_perc,
alarm_ref_blend_perc,
track_motion,
signal_check_colour,
embed_exif,
purpose,
0,
0
);
int n_zones = 0;
if ( load_zones )
{
Zone **zones = 0;
n_zones = Zone::Load( monitor, zones );
monitor->AddZones( n_zones, zones );
monitor->AddPrivacyBitmask( zones );
}
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones );
}
if ( mysql_errno( &dbconn ) )
{ {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); #if ZM_HAS_V4L
exit( mysql_errno( &dbconn ) ); camera = new LocalCamera(
id,
device.c_str(),
channel,
format,
v4l_multi_buffer,
v4l_captures_per_frame,
method,
cam_width,
cam_height,
colours,
palette,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE,
extras
);
#else // ZM_HAS_V4L
Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id );
#endif // ZM_HAS_V4L
} }
// Yadda yadda else if ( type == "Remote" )
mysql_free_result( result ); {
if ( protocol == "http" )
{
camera = new RemoteCameraHttp(
id,
method.c_str(),
host.c_str(),
port.c_str(),
path.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
}
else if ( protocol == "rtsp" )
{
#if HAVE_LIBAVFORMAT
camera = new RemoteCameraRtsp(
id,
method.c_str(),
host.c_str(),
port.c_str(),
path.c_str(),
cam_width,
cam_height,
rtsp_describe,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBAVFORMAT
Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
#endif // HAVE_LIBAVFORMAT
}
else
{
Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
}
}
else if ( type == "File" )
{
camera = new FileCamera(
id,
path.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
}
else if ( type == "Ffmpeg" )
{
#if HAVE_LIBAVFORMAT
camera = new FfmpegCamera(
id,
path.c_str(),
method,
options,
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBAVFORMAT
Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id );
#endif // HAVE_LIBAVFORMAT
}
else if (type == "Libvlc")
{
#if HAVE_LIBVLC
camera = new LibvlcCamera(
id,
path.c_str(),
method,
options,
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBVLC
Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id );
#endif // HAVE_LIBVLC
}
else if ( type == "cURL" )
{
#if HAVE_LIBCURL
camera = new cURLCamera(
id,
path.c_str(),
user.c_str(),
pass.c_str(),
cam_width,
cam_height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE
);
#else // HAVE_LIBCURL
Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id );
#endif // HAVE_LIBCURL
}
else
{
Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id );
}
monitor = new Monitor(
id,
name.c_str(),
server_id,
function,
enabled,
linked_monitors.c_str(),
camera,
orientation,
deinterlacing,
savejpegs,
videowriter,
encoderparams,
event_prefix.c_str(),
label_format.c_str(),
Coord( label_x, label_y ),
label_size,
image_buffer_count,
warmup_count,
pre_event_count,
post_event_count,
stream_replay_buffer,
alarm_frame_count,
section_length,
frame_skip,
motion_frame_skip,
analysis_fps,
analysis_update_delay,
capture_delay,
alarm_capture_delay,
fps_report_interval,
ref_blend_perc,
alarm_ref_blend_perc,
track_motion,
signal_check_colour,
embed_exif,
purpose,
0,
0
);
int n_zones = 0;
if ( load_zones )
{
Zone **zones = 0;
n_zones = Zone::Load( monitor, zones );
monitor->AddZones( n_zones, zones );
monitor->AddPrivacyBitmask( zones );
}
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones );
return( monitor ); return( monitor );
} }
@ -3112,17 +3083,17 @@ int Monitor::Capture()
{ {
static int FirstCapture = 1; static int FirstCapture = 1;
int captureResult; int captureResult;
int index = image_count%image_buffer_count; int index = image_count%image_buffer_count;
Image* capture_image = image_buffer[index].image; Image* capture_image = image_buffer[index].image;
if ( (deinterlacing & 0xff) == 4) { if ( (deinterlacing & 0xff) == 4) {
if ( FirstCapture != 1 ) { if ( FirstCapture != 1 ) {
/* Copy the next image into the shared memory */ /* Copy the next image into the shared memory */
capture_image->CopyBuffer(*(next_buffer.image)); capture_image->CopyBuffer(*(next_buffer.image));
} }
/* Capture a new next image */ /* Capture a new next image */
//Check if FFMPEG camera //Check if FFMPEG camera
if((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo()){ if((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo()){
@ -3167,18 +3138,18 @@ int Monitor::Capture()
if ( captureResult == 1 ) if ( captureResult == 1 )
{ {
/* Deinterlacing */ /* Deinterlacing */
if ( (deinterlacing & 0xff) == 1 ) { if ( (deinterlacing & 0xff) == 1 ) {
capture_image->Deinterlace_Discard(); capture_image->Deinterlace_Discard();
} else if ( (deinterlacing & 0xff) == 2 ) { } else if ( (deinterlacing & 0xff) == 2 ) {
capture_image->Deinterlace_Linear(); capture_image->Deinterlace_Linear();
} else if ( (deinterlacing & 0xff) == 3 ) { } else if ( (deinterlacing & 0xff) == 3 ) {
capture_image->Deinterlace_Blend(); capture_image->Deinterlace_Blend();
} else if ( (deinterlacing & 0xff) == 4 ) { } else if ( (deinterlacing & 0xff) == 4 ) {
capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff ); capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff );
} else if ( (deinterlacing & 0xff) == 5 ) { } else if ( (deinterlacing & 0xff) == 5 ) {
capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff );
} }
if ( orientation != ROTATE_0 ) if ( orientation != ROTATE_0 )
@ -3211,7 +3182,7 @@ int Monitor::Capture()
if ( capture_image->Size() > camera->ImageSize() ) if ( capture_image->Size() > camera->ImageSize() )
{ {
Error( "Captured image %d does not match expected size %d check width, height and colour depth",capture_image->Size(),camera->ImageSize() ); Error( "Captured image %d does not match expected size %d check width, height and colour depth",capture_image->Size(),camera->ImageSize() );
return( -1 ); return( -1 );
} }
@ -3591,7 +3562,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
} }
if (zone->CheckExtendAlarmCount()) { if (zone->CheckExtendAlarmCount()) {
alarm=true; alarm=true;
zone->SetAlarm(); zone->SetAlarm();
} else { } else {
zone->ClearAlarm(); zone->ClearAlarm();
} }
@ -4043,6 +4014,11 @@ void MonitorStream::processCommand( const CmdMsg *msg )
Debug( 1, "Got SCALE command, to %d", scale ); Debug( 1, "Got SCALE command, to %d", scale );
break; break;
} }
case CMD_QUIT :
{
Info ("User initiated exit - CMD_QUIT");
break;
}
case CMD_QUERY : case CMD_QUERY :
{ {
Debug( 1, "Got QUERY command, sending STATUS" ); Debug( 1, "Got QUERY command, sending STATUS" );
@ -4108,6 +4084,10 @@ void MonitorStream::processCommand( const CmdMsg *msg )
} }
} }
// quit after sending a status, if this was a quit request
if ((MsgCommand)msg->msg_data[0]==CMD_QUIT)
exit(0);
updateFrameRate( monitor->GetFPS() ); updateFrameRate( monitor->GetFPS() );
} }
@ -4558,7 +4538,7 @@ void MonitorStream::runStream()
} }
} }
} }
if ( swap_path ) free( swap_path ); if ( swap_path ) free( swap_path );
closeComms(); closeComms();
} }

View File

@ -226,6 +226,7 @@ protected:
// These are read from the DB and thereafter remain unchanged // These are read from the DB and thereafter remain unchanged
unsigned int id; unsigned int id;
char name[64]; char name[64];
unsigned int server_id;
Function function; // What the monitor is doing Function function; // What the monitor is doing
bool enabled; // Whether the monitor is enabled or asleep bool enabled; // Whether the monitor is enabled or asleep
unsigned int width; // Normally the same as the camera, but not if partly rotated unsigned int width; // Normally the same as the camera, but not if partly rotated
@ -331,7 +332,7 @@ protected:
public: public:
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. // OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
//bool OurCheckAlarms( Zone *zone, const Image *pImage ); //bool OurCheckAlarms( Zone *zone, const Image *pImage );
Monitor( int p_id, const char *p_name, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, int p_savejpegs, int p_videowriter, std::string p_encoderparams, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, int p_savejpegs, int p_videowriter, std::string p_encoderparams, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 );
~Monitor(); ~Monitor();
void AddZones( int p_n_zones, Zone *p_zones[] ); void AddZones( int p_n_zones, Zone *p_zones[] );
@ -457,7 +458,7 @@ public:
#if HAVE_LIBAVFORMAT #if HAVE_LIBAVFORMAT
static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose );
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT
static Monitor *Load( int id, bool load_zones, Purpose purpose ); static Monitor *Load( unsigned int id, bool load_zones, Purpose purpose );
//void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y ); //void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y );
//void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 ); //void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 );
//void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); //void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 );

View File

@ -57,7 +57,7 @@ protected:
} DataMsg; } DataMsg;
typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType; typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType;
typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUERY=99 } MsgCommand; typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUIT, CMD_QUERY=99 } MsgCommand;
protected: protected:
Monitor *monitor; Monitor *monitor;

View File

@ -1,18 +1,45 @@
#!/bin/bash #!/bin/bash
if [ "$1" == "clean" ]; then
read -p "Do you really want to delete existing packages? [y/N]"
[[ $REPLY == [yY] ]] && { rm -fr zoneminder*.build zoneminder*.changes zoneminder*.deb; echo "Existing package files deleted"; } || { echo "Packages have NOT been deleted"; }
exit;
fi
DATE=`date -R` DATE=`date -R`
DISTRO=$1 DISTRO=$1
SNAPSHOT=$2 SNAPSHOT=$2
if [ "$SNAPSHOT" == "stable" ]; then
SNAPSHOT="";
fi;
TYPE=$3 TYPE=$3
if [ "$TYPE" == "" ]; then if [ "$TYPE" == "" ]; then
TYPE="source"; TYPE="source";
fi; fi;
BRANCH=$4
if [ ! -d 'zoneminder_release' ]; then if [ ! -d 'zoneminder_release' ]; then
git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder_release git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder_release
fi;
if [ "$BRANCH" != "" ]; then
cd zoneminder_release
if [ "$BRANCH" == "stable" ]; then
BRANCH=$(git describe --tags $(git rev-list --tags --max-count=1));
echo "Latest stable branch is $BRANCH";
fi
git checkout $BRANCH
cd ../
fi; fi;
VERSION=`cat zoneminder_release/version` VERSION=`cat zoneminder_release/version`
if [ $VERSION == "" ]; then if [ $VERSION == "" ]; then
exit 1; exit 1;
fi; fi;
echo "Doing $TYPE release zoneminder_$VERSION-$DISTRO-$SNAPSHOT"; echo "Doing $TYPE release zoneminder_$VERSION-$DISTRO-$SNAPSHOT";
mv zoneminder_release zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig mv zoneminder_release zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
@ -20,9 +47,9 @@ cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
git submodule init git submodule init
git submodule update --init --recursive git submodule update --init --recursive
if [ $DISTRO == "trusty" ]; then if [ $DISTRO == "trusty" ]; then
cp -r distros/ubuntu1204_cmake debian ln -sf distros/ubuntu1204_cmake debian
else else
cp -r distros/ubuntu1504_cmake debian ln -sf distros/ubuntu1504_cmake debian
fi; fi;
cat <<EOF > debian/changelog cat <<EOF > debian/changelog
@ -33,15 +60,26 @@ zoneminder ($VERSION-$DISTRO-$SNAPSHOT) $DISTRO; urgency=medium
-- Isaac Connor <iconnor@connortechnology.com> $DATE -- Isaac Connor <iconnor@connortechnology.com> $DATE
EOF EOF
rm -rf .git #rm -rf .git
rm .gitignore #rm .gitignore
cd ../ #cd ../
tar zcf zoneminder_$VERSION-$DISTRO.orig.tar.gz zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig #tar zcf zoneminder_$VERSION-$DISTRO.orig.tar.gz zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig #cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
if [ $TYPE == "binary" ]; then if [ $TYPE == "binary" ]; then
debuild -k52C7377E debuild
else else
debuild -S -sa -k52C7377E if [ $TYPE == "local" ]; then
debuild -i -us -uc -b
else
debuild -S -sa
fi;
fi; fi;
cd ../ cd ../
rm -fr zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
read -p "Do you want to keep the checked out version of Zoneminder (incase you want to modify it later) [y/N]"
[[ $REPLY == [yY] ]] && { mv zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig zoneminder_release; echo "The checked out copy is preserved in zoneminder_release"; } || { rm -fr zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig; echo "The checked out copy has been deleted"; }
echo "Done!"

View File

@ -1 +1 @@
1.28.109 1.29.0

View File

@ -1,5 +1,6 @@
<?php <?php
require_once( 'includes/control_functions.php' ); require_once( 'includes/control_functions.php' );
require_once( 'includes/Monitor.php' );
// Monitor control actions, require a monitor id and control view permissions for that monitor // Monitor control actions, require a monitor id and control view permissions for that monitor
if ( empty($_REQUEST['id']) ) if ( empty($_REQUEST['id']) )
@ -7,7 +8,7 @@ if ( empty($_REQUEST['id']) )
if ( canView( 'Control', $_REQUEST['id'] ) ) if ( canView( 'Control', $_REQUEST['id'] ) )
{ {
$monitor = dbFetchOne( 'select C.*,M.* from Monitors as M inner join Controls as C on (M.ControlId = C.Id ) where M.Id = ?', NULL, array($_REQUEST['id']) ); $monitor = new Monitor( $_REQUEST['id'] );
$ctrlCommand = buildControlCommand( $monitor ); $ctrlCommand = buildControlCommand( $monitor );
@ -17,7 +18,7 @@ if ( canView( 'Control', $_REQUEST['id'] ) )
if ( !$socket ) if ( !$socket )
ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) ); ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) );
$sock_file = ZM_PATH_SOCKS.'/zmcontrol-'.$monitor['Id'].'.sock'; $sock_file = ZM_PATH_SOCKS.'/zmcontrol-'.$monitor->Id().'.sock';
if ( @socket_connect( $socket, $sock_file ) ) if ( @socket_connect( $socket, $sock_file ) )
{ {
$options = array(); $options = array();
@ -36,7 +37,7 @@ if ( canView( 'Control', $_REQUEST['id'] ) )
} }
else else
{ {
$ctrlCommand .= " --id=".$monitor['Id']; $ctrlCommand .= " --id=".$monitor->Id();
// Can't connect so use script // Can't connect so use script
$ctrlStatus = ''; $ctrlStatus = '';

View File

@ -31,6 +31,13 @@ switch ( $_REQUEST['task'] )
if ( !canView( 'System' ) ) if ( !canView( 'System' ) )
ajaxError( 'Insufficient permissions to view log entries' ); ajaxError( 'Insufficient permissions to view log entries' );
$servers = Server::find_all();
$servers_by_Id = array();
# There is probably a better way to do this.
foreach ( $servers as $server ) {
$servers_by_Id[$server->Id()] = $server;
}
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
$limit = isset($_POST['limit'])?$_POST['limit']:100; $limit = isset($_POST['limit'])?$_POST['limit']:100;
@ -38,7 +45,7 @@ switch ( $_REQUEST['task'] )
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; $sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey';
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
$filterFields = array( 'Component', 'Pid', 'Level', 'File', 'Line' ); $filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
$total = dbFetchOne( "SELECT count(*) AS Total FROM Logs", 'Total' ); $total = dbFetchOne( "SELECT count(*) AS Total FROM Logs", 'Total' );
$sql = 'SELECT * FROM Logs'; $sql = 'SELECT * FROM Logs';
@ -66,6 +73,7 @@ switch ( $_REQUEST['task'] )
$logs = array(); $logs = array();
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) { foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
$logs[] = $log; $logs[] = $log;
} }
$options = array(); $options = array();
@ -96,6 +104,12 @@ switch ( $_REQUEST['task'] )
else else
$options[$field][$value] = "DB".$value; $options[$field][$value] = "DB".$value;
} }
elseif ( $field == 'ServerId' )
{
foreach( dbFetchAll( $sql, $field, array_values($fieldValues) ) as $value )
$options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : '';
}
else else
{ {
foreach( dbFetchAll( $sql, $field, array_values( $fieldValues ) ) as $value ) foreach( dbFetchAll( $sql, $field, array_values( $fieldValues ) ) as $value )
@ -136,6 +150,13 @@ switch ( $_REQUEST['task'] )
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; $sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey';
$sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'asc'; $sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'asc';
$servers = Server::find_all();
$servers_by_Id = array();
# There is probably a better way to do this.
foreach ( $servers as $server ) {
$servers_by_Id[$server->Id()] = $server;
}
$sql = "select * from Logs"; $sql = "select * from Logs";
$where = array(); $where = array();
$values = array(); $values = array();
@ -195,6 +216,7 @@ switch ( $_REQUEST['task'] )
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) foreach ( dbFetchAll( $sql, NULL, $values ) as $log )
{ {
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
$logs[] = $log; $logs[] = $log;
} }
switch( $format ) switch( $format )
@ -212,10 +234,20 @@ switch ( $_REQUEST['task'] )
} }
case 'tsv' : case 'tsv' :
{ {
fprintf( $exportFP, translate('DateTime')."\t".translate('Component')."\t".translate('Pid')."\t".translate('Level')."\t".translate('Message')."\t".translate('File')."\t".translate('Line')."\n" ); # This line doesn't need fprintf, it could use fwrite
fprintf( $exportFP, join( "\t",
translate('DateTime'),
translate('Component'),
translate('Server'),
translate('Pid'),
translate('Level'),
translate('Message'),
translate('File'),
translate('Line')
)."\n" );
foreach ( $logs as $log ) foreach ( $logs as $log )
{ {
fprintf( $exportFP, "%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
} }
break; break;
} }
@ -265,7 +297,7 @@ tr.log-dbg td {
<p>'.count($logs).' '.translate('Logs').'</p> <p>'.count($logs).' '.translate('Logs').'</p>
<table> <table>
<tbody> <tbody>
<tr><th>'.translate('DateTime').'</th><th>'.translate('Component').'</th><th>'.translate('Pid').'</th><th>'.translate('Level').'</th><th>'.translate('Message').'</th><th>'.translate('File').'</th><th>'.translate('Line').'</th></tr> <tr><th>'.translate('DateTime').'</th><th>'.translate('Component').'</th><th>'.translate('Server').'</th><th>'.translate('Pid').'</th><th>'.translate('Level').'</th><th>'.translate('Message').'</th><th>'.translate('File').'</th><th>'.translate('Line').'</th></tr>
' ); ' );
foreach ( $logs as $log ) foreach ( $logs as $log )
{ {
@ -275,7 +307,7 @@ tr.log-dbg td {
elseif ( $classLevel > Logger::DEBUG ) elseif ( $classLevel > Logger::DEBUG )
$classLevel = Logger::DEBUG; $classLevel = Logger::DEBUG;
$logClass = 'log-'.strtolower(Logger::$codes[$classLevel]); $logClass = 'log-'.strtolower(Logger::$codes[$classLevel]);
fprintf( $exportFP, " <tr class=\"%s\"><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $logClass, $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); fprintf( $exportFP, " <tr class=\"%s\"><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
} }
fwrite( $exportFP, fwrite( $exportFP,
' </tbody> ' </tbody>
@ -298,7 +330,7 @@ tr.log-dbg td {
</filter>' ); </filter>' );
fwrite( $exportFP, fwrite( $exportFP,
' <columns> ' <columns>
<column field="datetime">'.translate('DateTime').'</column><column field="component">'.translate('Component').'</column><column field="pid">'.translate('Pid').'</column><column field="level">'.translate('Level').'</column><column field="message">'.translate('Message').'</column><column field="file">'.translate('File').'</column><column field="line">'.translate('Line').'</column> <column field="datetime">'.translate('DateTime').'</column><column field="component">'.translate('Component').'</column><column field="'.translate('Server').'</column><column field="pid">'.translate('Pid').'</column><column field="level">'.translate('Level').'</column><column field="message">'.translate('Message').'</column><column field="file">'.translate('File').'</column><column field="line">'.translate('Line').'</column>
</columns> </columns>
<logs count="'.count($logs).'"> <logs count="'.count($logs).'">
' ); ' );
@ -308,12 +340,13 @@ tr.log-dbg td {
" <log> " <log>
<datetime>%s</datetime> <datetime>%s</datetime>
<component>%s</component> <component>%s</component>
<server>%s</server>
<pid>%d</pid> <pid>%d</pid>
<level>%s</level> <level>%s</level>
<message><![CDATA[%s]]></message> <message><![CDATA[%s]]></message>
<file>%s</file> <file>%s</file>
<line>%d</line> <line>%d</line>
</log>\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] ); </log>\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] );
} }
fwrite( $exportFP, fwrite( $exportFP,
' </logs> ' </logs>

View File

@ -6,6 +6,8 @@ web_DATA = \
config.php config.php
dist_web_DATA = \ dist_web_DATA = \
Monitor.php \
Server.php \
actions.php \ actions.php \
database.php \ database.php \
functions.php \ functions.php \

84
web/includes/Monitor.php Normal file
View File

@ -0,0 +1,84 @@
<?php
require_once( 'database.php' );
require_once( 'Server.php' );
class Monitor {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Server record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Monitor Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
if ( $this->{'Controllable'} ) {
$s = dbFetchOne( 'SELECT * FROM Controls WHERE Id=?', NULL, array( $this->{'ControlId'} ) );
foreach ($s as $k => $v) {
if ( $k == 'Id' ) {
continue;
}
$this->{$k} = $v;
}
}
} else {
Error("No row for Monitor " . $IdOrRow );
}
} // end function __construct
public function Server() {
return new Server( $this->{'ServerId'} );
}
public function __call( $fn, array $args){
if(isset($this->{$fn})){
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
}
}
public function getStreamSrc( $args, $querySep='&amp;' ) {
if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) {
$Server = new Server( $this->{'ServerId'} );
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname().ZM_PATH_ZMS;
} else {
$streamSrc = ZM_BASE_URL.ZM_PATH_ZMS;
}
$args[] = "monitor=".$this->{'Id'};
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'];
$args[] = "pass=".$_SESSION['password'];
} elseif ( ZM_AUTH_RELAY == "none" ) {
$args[] = "user=".$_SESSION['username'];
}
}
if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) {
$args[] = "connkey=".$GLOBALS['connkey'];
}
if ( ZM_RAND_STREAM ) {
$args[] = "rand=".time();
}
if ( count($args) ) {
$streamSrc .= "?".join( $querySep, $args );
}
return( $streamSrc );
} // end function etStreamSrc
}
?>

57
web/includes/Server.php Normal file
View File

@ -0,0 +1,57 @@
<?php
require_once( 'database.php' );
class Server {
public function __construct( $IdOrRow = NULL ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Server record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
} else {
$this->{'Name'} = '';
$this->{'Hostname'} = '';
}
}
public static function find_all() {
$servers = array();
$result = dbQuery( 'SELECT * FROM Servers ORDER BY Name');
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server' );
foreach ( $results as $row => $server_obj ) {
$servers[] = $server_obj;
}
return $servers;
}
public function Url() {
if ( $this->Id() ) {
return ZM_BASE_PROTOCOL . '://'. $this->Hostname();
} else {
return '';
}
}
public function Hostname() {
if ( isset( $this->{'Hostname'} ) and ( $this->{'Hostname'} != '' ) ) {
return $this->{'Hostname'};
}
return $this->{'Name'};
}
public function __call( $fn, array $args= NULL){
if(isset($this->{$fn})){
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
}
}
}
?>

View File

@ -246,13 +246,14 @@ if ( !empty($action) )
if ( !empty($_REQUEST['mid']) && canView( 'Control', $_REQUEST['mid'] ) ) if ( !empty($_REQUEST['mid']) && canView( 'Control', $_REQUEST['mid'] ) )
{ {
require_once( 'control_functions.php' ); require_once( 'control_functions.php' );
require_once( 'Monitor.php' );
$mid = validInt($_REQUEST['mid']); $mid = validInt($_REQUEST['mid']);
if ( $action == "control" ) if ( $action == "control" )
{ {
$monitor = dbFetchOne( "select C.*,M.* from Monitors as M inner join Controls as C on (M.ControlId = C.Id) where M.Id = ?", NULL, array($mid) ); $monitor = new Monitor( $mid );
$ctrlCommand = buildControlCommand( $monitor ); $ctrlCommand = buildControlCommand( $monitor );
sendControlCommand( $monitor['Id'], $ctrlCommand ); sendControlCommand( $monitor->Id(), $ctrlCommand );
} }
elseif ( $action == "settings" ) elseif ( $action == "settings" )
{ {
@ -768,7 +769,7 @@ if ( !empty($action) )
{ {
if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'server' ) ) { if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'server' ) ) {
if ( $action == "save" ) { if ( $action == "Save" ) {
if ( !empty($_REQUEST['id']) ) if ( !empty($_REQUEST['id']) )
$dbServer = dbFetchOne( "SELECT * FROM Servers WHERE Id=?", NULL, array($_REQUEST['id']) ); $dbServer = dbFetchOne( "SELECT * FROM Servers WHERE Id=?", NULL, array($_REQUEST['id']) );
else else
@ -792,6 +793,8 @@ if ( !empty($action) )
dbQuery( "DELETE FROM Servers WHERE Id=?", array($Id) ); dbQuery( "DELETE FROM Servers WHERE Id=?", array($Id) );
} }
$refreshParent = true; $refreshParent = true;
} else {
Error( "Unknown action $action in saving Server" );
} }
} else if ( $action == "version" && isset($_REQUEST['option']) ) } else if ( $action == "version" && isset($_REQUEST['option']) )

View File

@ -167,4 +167,25 @@ function loadConfig( $defineConsts=true )
//print_r( $configCats ); //print_r( $configCats );
} }
require_once( 'logger.php' );
// For Human-readability, user ZM_SERVER in zm.conf, and convert it here to a ZM_SERVER_ID
if ( ! defined('ZM_SERVER_ID') ) {
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
if ( ! $server_id ) {
Error("ZM_SERVER_NAME set to " . ZM_SERVER_NAME . " in config, but not found in Servers table.");
} else {
define( 'ZM_SERVER_ID', $server_id );
}
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST));
if ( ! $server_id ) {
Error("ZM_SERVER_HOST set to " . ZM_SERVER_HOST . " in config, but not found in Servers table.");
} else {
define( 'ZM_SERVER_ID', $server_id );
}
}
}
?> ?>

View File

@ -20,9 +20,9 @@ function buildControlCommand( $monitor )
case 'focus' : case 'focus' :
{ {
$factor = $_REQUEST['yge']/100; $factor = $_REQUEST['yge']/100;
if ( $monitor['HasFocusSpeed'] ) if ( $monitor->HasFocusSpeed() )
{ {
$speed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$factor))); $speed = intval(round($monitor->MinFocusSpeed()+(($monitor->MaxFocusSpeed()-$monitor->MinFocusSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -30,15 +30,15 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinFocusStep']+(($monitor['MaxFocusStep']-$monitor['MinFocusStep'])*$factor))); $step = intval(round($monitor->MinFocusStep()+(($monitor->MaxFocusStep()-$monitor->MinFocusStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowSpeed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$slow))); $slowSpeed = intval(round($monitor->MinFocusSpeed()+(($monitor->MaxFocusSpeed()-$monitor->MinFocusSpeed())*$slow)));
if ( $speed < $slowSpeed ) if ( $speed < $slowSpeed )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -52,9 +52,9 @@ function buildControlCommand( $monitor )
case 'zoom' : case 'zoom' :
{ {
$factor = $_REQUEST['yge']/100; $factor = $_REQUEST['yge']/100;
if ( $monitor['HasZoomSpeed'] ) if ( $monitor->HasZoomSpeed() )
{ {
$speed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$factor))); $speed = intval(round($monitor->MinZoomSpeed()+(($monitor->MaxZoomSpeed()-$monitor->MinZoomSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -62,15 +62,15 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinZoomStep']+(($monitor['MaxZoomStep']-$monitor['MinZoomStep'])*$factor))); $step = intval(round($monitor->MinZoomStep()+(($monitor->MaxZoomStep()-$monitor->MinZoomStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowSpeed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$slow))); $slowSpeed = intval(round($monitor->MinZoomSpeed()+(($monitor->MaxZoomSpeed()-$monitor->MinZoomSpeed())*$slow)));
if ( $speed < $slowSpeed ) if ( $speed < $slowSpeed )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -84,9 +84,9 @@ function buildControlCommand( $monitor )
case 'iris' : case 'iris' :
{ {
$factor = $_REQUEST['yge']/100; $factor = $_REQUEST['yge']/100;
if ( $monitor['HasIrisSpeed'] ) if ( $monitor->HasIrisSpeed() )
{ {
$speed = intval(round($monitor['MinIrisSpeed']+(($monitor['MaxIrisSpeed']-$monitor['MinIrisSpeed'])*$factor))); $speed = intval(round($monitor->MinIrisSpeed()+(($monitor->MaxIrisSpeed()-$monitor->MinIrisSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -94,7 +94,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinIrisStep']+(($monitor['MaxIrisStep']-$monitor['MinIrisStep'])*$factor))); $step = intval(round($monitor->MinIrisStep()+(($monitor->MaxIrisStep()-$monitor->MinIrisStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -104,9 +104,9 @@ function buildControlCommand( $monitor )
case 'white' : case 'white' :
{ {
$factor = $_REQUEST['yge']/100; $factor = $_REQUEST['yge']/100;
if ( $monitor['HasWhiteSpeed'] ) if ( $monitor->HasWhiteSpeed() )
{ {
$speed = intval(round($monitor['MinWhiteSpeed']+(($monitor['MaxWhiteSpeed']-$monitor['MinWhiteSpeed'])*$factor))); $speed = intval(round($monitor->MinWhiteSpeed()+(($monitor->MaxWhiteSpeed()-$monitor->MinWhiteSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -114,7 +114,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinWhiteStep']+(($monitor['MaxWhiteStep']-$monitor['MinWhiteStep'])*$factor))); $step = intval(round($monitor->MinWhiteStep()+(($monitor->MaxWhiteStep()-$monitor->MinWhiteStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -124,9 +124,9 @@ function buildControlCommand( $monitor )
case 'gain' : case 'gain' :
{ {
$factor = $_REQUEST['yge']/100; $factor = $_REQUEST['yge']/100;
if ( $monitor['HasGainSpeed'] ) if ( $monitor->HasGainSpeed() )
{ {
$speed = intval(round($monitor['MinGainSpeed']+(($monitor['MaxGainSpeed']-$monitor['MinGainSpeed'])*$factor))); $speed = intval(round($monitor->MinGainSpeed()+(($monitor->MaxGainSpeed()-$monitor->MinGainSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -134,7 +134,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinGainStep']+(($monitor['MaxGainStep']-$monitor['MinGainStep'])*$factor))); $step = intval(round($monitor->MinGainStep()+(($monitor->MaxGainStep()-$monitor->MinGainStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -146,7 +146,7 @@ function buildControlCommand( $monitor )
$xFactor = empty($_REQUEST['xge'])?0:$_REQUEST['xge']/100; $xFactor = empty($_REQUEST['xge'])?0:$_REQUEST['xge']/100;
$yFactor = empty($_REQUEST['yge'])?0:$_REQUEST['yge']/100; $yFactor = empty($_REQUEST['yge'])?0:$_REQUEST['yge']/100;
if ( $monitor['Orientation'] != '0' ) if ( $monitor->Orientation() != '0' )
{ {
$conversions = array( $conversions = array(
'90' => array( '90' => array(
@ -200,48 +200,48 @@ function buildControlCommand( $monitor )
'DownRight' => 'UpRight', 'DownRight' => 'UpRight',
), ),
); );
$new_dirn = $conversions[$monitor['Orientation']][$dirn]; $new_dirn = $conversions[$monitor->Orientation()][$dirn];
$_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] ); $_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] );
$dirn = $new_dirn; $dirn = $new_dirn;
} }
if ( $monitor['HasPanSpeed'] && $xFactor ) if ( $monitor->HasPanSpeed() && $xFactor )
{ {
if ( $monitor['HasTurboPan'] ) if ( $monitor->HasTurboPan() )
{ {
if ( $xFactor >= $turbo ) if ( $xFactor >= $turbo )
{ {
$panSpeed = $monitor['TurboPanSpeed']; $panSpeed = $monitor->TurboPanSpeed();
} }
else else
{ {
$xFactor = $xFactor/$turbo; $xFactor = $xFactor/$turbo;
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
else else
{ {
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
$ctrlCommand .= " --panspeed=".$panSpeed; $ctrlCommand .= " --panspeed=".$panSpeed;
} }
if ( $monitor['HasTiltSpeed'] && $yFactor ) if ( $monitor->HasTiltSpeed() && $yFactor )
{ {
if ( $monitor['HasTurboTilt'] ) if ( $monitor->HasTurboTilt() )
{ {
if ( $yFactor >= $turbo ) if ( $yFactor >= $turbo )
{ {
$tiltSpeed = $monitor['TurboTiltSpeed']; $tiltSpeed = $monitor->TurboTiltSpeed();
} }
else else
{ {
$yFactor = $yFactor/$turbo; $yFactor = $yFactor/$turbo;
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
else else
{ {
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
$ctrlCommand .= " --tiltspeed=".$tiltSpeed; $ctrlCommand .= " --tiltspeed=".$tiltSpeed;
} }
@ -252,22 +252,22 @@ function buildControlCommand( $monitor )
{ {
if ( preg_match( '/(Left|Right)$/', $dirn ) ) if ( preg_match( '/(Left|Right)$/', $dirn ) )
{ {
$panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); $panStep = intval(round($monitor->MinPanStep()+(($monitor->MaxPanStep()-$monitor->MinPanStep())*$xFactor)));
$ctrlCommand .= " --panstep=".$panStep; $ctrlCommand .= " --panstep=".$panStep;
} }
if ( preg_match( '/^(Up|Down)/', $dirn ) ) if ( preg_match( '/^(Up|Down)/', $dirn ) )
{ {
$tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); $tiltStep = intval(round($monitor->MinTiltStep()+(($monitor->MaxTiltStep()-$monitor->MinTiltStep())*$yFactor)));
$ctrlCommand .= " --tiltstep=".$tiltStep; $ctrlCommand .= " --tiltstep=".$tiltStep;
} }
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); $slowPanSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$slow)));
$slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); $slowTiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$slow)));
if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -286,22 +286,22 @@ function buildControlCommand( $monitor )
{ {
$x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] );
$y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] );
switch ( $monitor['Orientation'] ) switch ( $monitor->Orientation() )
{ {
case '0' : case '0' :
case '180' : case '180' :
case 'hori' : case 'hori' :
case 'vert' : case 'vert' :
$width = $monitor['Width']; $width = $monitor->Width();
$height = $monitor['Height']; $height = $monitor->Height();
break; break;
case '90' : case '90' :
case '270' : case '270' :
$width = $monitor['Height']; $width = $monitor->Height();
$height = $monitor['Width']; $height = $monitor->Width();
break; break;
} }
switch ( $monitor['Orientation'] ) switch ( $monitor->Orientation() )
{ {
case '90' : case '90' :
$tempY = $y; $tempY = $y;
@ -332,12 +332,12 @@ function buildControlCommand( $monitor )
$x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] );
$y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] );
$halfWidth = $monitor['Width'] / 2; $halfWidth = $monitor->Width() / 2;
$halfHeight = $monitor['Height'] / 2; $halfHeight = $monitor->Height() / 2;
$xFactor = ($x - $halfWidth)/$halfWidth; $xFactor = ($x - $halfWidth)/$halfWidth;
$yFactor = ($y - $halfHeight)/$halfHeight; $yFactor = ($y - $halfHeight)/$halfHeight;
switch ( $monitor['Orientation'] ) switch ( $monitor->Orientation() )
{ {
case '90' : case '90' :
$tempYFactor = $y; $tempYFactor = $y;
@ -396,52 +396,52 @@ function buildControlCommand( $monitor )
$xFactor = abs($xFactor); $xFactor = abs($xFactor);
$yFactor = abs($yFactor); $yFactor = abs($yFactor);
if ( $monitor['HasPanSpeed'] && $xFactor ) if ( $monitor->HasPanSpeed() && $xFactor )
{ {
if ( $monitor['HasTurboPan'] ) if ( $monitor->HasTurboPan() )
{ {
if ( $xFactor >= $turbo ) if ( $xFactor >= $turbo )
{ {
$panSpeed = $monitor['TurboPanSpeed']; $panSpeed = $monitor->TurboPanSpeed();
} }
else else
{ {
$xFactor = $xFactor/$turbo; $xFactor = $xFactor/$turbo;
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
else else
{ {
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
if ( $monitor['HasTiltSpeed'] && $yFactor ) if ( $monitor->HasTiltSpeed() && $yFactor )
{ {
if ( $monitor['HasTurboTilt'] ) if ( $monitor->HasTurboTilt() )
{ {
if ( $yFactor >= $turbo ) if ( $yFactor >= $turbo )
{ {
$tiltSpeed = $monitor['TurboTiltSpeed']; $tiltSpeed = $monitor->TurboTiltSpeed();
} }
else else
{ {
$yFactor = $yFactor/$turbo; $yFactor = $yFactor/$turbo;
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
else else
{ {
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
if ( preg_match( '/(Left|Right)$/', $dirn ) ) if ( preg_match( '/(Left|Right)$/', $dirn ) )
{ {
$panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); $panStep = intval(round($monitor->MinPanStep()+(($monitor->MaxPanStep()-$monitor->MinPanStep())*$xFactor)));
$ctrlCommand .= " --panstep=".$panStep." --panspeed=".$panSpeed; $ctrlCommand .= " --panstep=".$panStep." --panspeed=".$panSpeed;
} }
if ( preg_match( '/^(Up|Down)/', $dirn ) ) if ( preg_match( '/^(Up|Down)/', $dirn ) )
{ {
$tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); $tiltStep = intval(round($monitor->MinTiltStep()+(($monitor->MaxTiltStep()-$monitor->MinTiltStep())*$yFactor)));
$ctrlCommand .= " --tiltstep=".$tiltStep." --tiltspeed=".$tiltSpeed; $ctrlCommand .= " --tiltstep=".$tiltStep." --tiltspeed=".$tiltSpeed;
} }
} }
@ -451,12 +451,12 @@ function buildControlCommand( $monitor )
$x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] );
$y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] );
$halfWidth = $monitor['Width'] / 2; $halfWidth = $monitor->Width() / 2;
$halfHeight = $monitor['Height'] / 2; $halfHeight = $monitor->Height() / 2;
$xFactor = ($x - $halfWidth)/$halfWidth; $xFactor = ($x - $halfWidth)/$halfWidth;
$yFactor = ($y - $halfHeight)/$halfHeight; $yFactor = ($y - $halfHeight)/$halfHeight;
switch ( $monitor['Orientation'] ) switch ( $monitor->Orientation() )
{ {
case '90' : case '90' :
$tempYFactor = $y; $tempYFactor = $y;
@ -515,42 +515,42 @@ function buildControlCommand( $monitor )
$xFactor = abs($xFactor); $xFactor = abs($xFactor);
$yFactor = abs($yFactor); $yFactor = abs($yFactor);
if ( $monitor['HasPanSpeed'] && $xFactor ) if ( $monitor->HasPanSpeed() && $xFactor )
{ {
if ( $monitor['HasTurboPan'] ) if ( $monitor->HasTurboPan() )
{ {
if ( $xFactor >= $turbo ) if ( $xFactor >= $turbo )
{ {
$panSpeed = $monitor['TurboPanSpeed']; $panSpeed = $monitor->TurboPanSpeed();
} }
else else
{ {
$xFactor = $xFactor/$turbo; $xFactor = $xFactor/$turbo;
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
else else
{ {
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
if ( $monitor['HasTiltSpeed'] && $yFactor ) if ( $monitor->HasTiltSpeed() && $yFactor )
{ {
if ( $monitor['HasTurboTilt'] ) if ( $monitor->HasTurboTilt() )
{ {
if ( $yFactor >= $turbo ) if ( $yFactor >= $turbo )
{ {
$tiltSpeed = $monitor['TurboTiltSpeed']; $tiltSpeed = $monitor->TurboTiltSpeed();
} }
else else
{ {
$yFactor = $yFactor/$turbo; $yFactor = $yFactor/$turbo;
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
else else
{ {
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
if ( preg_match( '/(Left|Right)$/', $dirn ) ) if ( preg_match( '/(Left|Right)$/', $dirn ) )
@ -561,10 +561,10 @@ function buildControlCommand( $monitor )
{ {
$ctrlCommand .= " --tiltspeed=".$tiltSpeed; $ctrlCommand .= " --tiltspeed=".$tiltSpeed;
} }
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); $slowPanSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$slow)));
$slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); $slowTiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$slow)));
if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -603,9 +603,9 @@ function buildControlCommand( $monitor )
break; break;
} }
} }
if ( $monitor['HasFocusSpeed'] ) if ( $monitor->HasFocusSpeed() )
{ {
$speed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$factor))); $speed = intval(round($monitor->MinFocusSpeed()+(($monitor->MaxFocusSpeed()-$monitor->MinFocusSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -613,15 +613,15 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinFocusStep']+(($monitor['MaxFocusStep']-$monitor['MinFocusStep'])*$factor))); $step = intval(round($monitor->MinFocusStep()+(($monitor->MaxFocusStep()-$monitor->MinFocusStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowSpeed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$slow))); $slowSpeed = intval(round($monitor->MinFocusSpeed()+(($monitor->MaxFocusSpeed()-$monitor->MinFocusSpeed())*$slow)));
if ( $speed < $slowSpeed ) if ( $speed < $slowSpeed )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -647,9 +647,9 @@ function buildControlCommand( $monitor )
break; break;
} }
} }
if ( $monitor['HasZoomSpeed'] ) if ( $monitor->HasZoomSpeed() )
{ {
$speed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$factor))); $speed = intval(round($monitor->MinZoomSpeed()+(($monitor->MaxZoomSpeed()-$monitor->MinZoomSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -657,15 +657,15 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinZoomStep']+(($monitor['MaxZoomStep']-$monitor['MinZoomStep'])*$factor))); $step = intval(round($monitor->MinZoomStep()+(($monitor->MaxZoomStep()-$monitor->MinZoomStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowSpeed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$slow))); $slowSpeed = intval(round($monitor->MinZoomSpeed()+(($monitor->MaxZoomSpeed()-$monitor->MinZoomSpeed())*$slow)));
if ( $speed < $slowSpeed ) if ( $speed < $slowSpeed )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -691,9 +691,9 @@ function buildControlCommand( $monitor )
break; break;
} }
} }
if ( $monitor['HasIrisSpeed'] ) if ( $monitor->HasIrisSpeed() )
{ {
$speed = intval(round($monitor['MinIrisSpeed']+(($monitor['MaxIrisSpeed']-$monitor['MinIrisSpeed'])*$factor))); $speed = intval(round($monitor->MinIrisSpeed()+(($monitor->MaxIrisSpeed()-$monitor->MinIrisSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -701,7 +701,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinIrisStep']+(($monitor['MaxIrisStep']-$monitor['MinIrisStep'])*$factor))); $step = intval(round($monitor->MinIrisStep()+(($monitor->MaxIrisStep()-$monitor->MinIrisStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -723,9 +723,9 @@ function buildControlCommand( $monitor )
break; break;
} }
} }
if ( $monitor['HasWhiteSpeed'] ) if ( $monitor->HasWhiteSpeed() )
{ {
$speed = intval(round($monitor['MinWhiteSpeed']+(($monitor['MaxWhiteSpeed']-$monitor['MinWhiteSpeed'])*$factor))); $speed = intval(round($monitor->MinWhiteSpeed()+(($monitor->MaxWhiteSpeed()-$monitor->MinWhiteSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -733,7 +733,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinWhiteStep']+(($monitor['MaxWhiteStep']-$monitor['MinWhiteStep'])*$factor))); $step = intval(round($monitor->MinWhiteStep()+(($monitor->MaxWhiteStep()-$monitor->MinWhiteStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -755,9 +755,9 @@ function buildControlCommand( $monitor )
break; break;
} }
} }
if ( $monitor['HasGainSpeed'] ) if ( $monitor->HasGainSpeed() )
{ {
$speed = intval(round($monitor['MinGainSpeed']+(($monitor['MaxGainSpeed']-$monitor['MinGainSpeed'])*$factor))); $speed = intval(round($monitor->MinGainSpeed()+(($monitor->MaxGainSpeed()-$monitor->MinGainSpeed())*$factor)));
$ctrlCommand .= " --speed=".$speed; $ctrlCommand .= " --speed=".$speed;
} }
switch( $mode ) switch( $mode )
@ -765,7 +765,7 @@ function buildControlCommand( $monitor )
case 'Abs' : case 'Abs' :
case 'Rel' : case 'Rel' :
{ {
$step = intval(round($monitor['MinGainStep']+(($monitor['MaxGainStep']-$monitor['MinGainStep'])*$factor))); $step = intval(round($monitor->MinGainStep()+(($monitor->MaxGainStep()-$monitor->MinGainStep())*$factor)));
$ctrlCommand .= " --step=".$step; $ctrlCommand .= " --step=".$step;
break; break;
} }
@ -794,7 +794,7 @@ function buildControlCommand( $monitor )
$xFactor = ($x+1)/$short_x; $xFactor = ($x+1)/$short_x;
} }
if ( $monitor['Orientation'] != '0' ) if ( $monitor->Orientation() != '0' )
{ {
$conversions = array( $conversions = array(
'90' => array( '90' => array(
@ -848,48 +848,48 @@ function buildControlCommand( $monitor )
'DownRight' => 'UpRight', 'DownRight' => 'UpRight',
), ),
); );
$new_dirn = $conversions[$monitor['Orientation']][$dirn]; $new_dirn = $conversions[$monitor->Orientation()][$dirn];
$_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] ); $_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] );
$dirn = $new_dirn; $dirn = $new_dirn;
} }
if ( $monitor['HasPanSpeed'] && $xFactor ) if ( $monitor->HasPanSpeed() && $xFactor )
{ {
if ( $monitor['HasTurboPan'] ) if ( $monitor->HasTurboPan() )
{ {
if ( $xFactor >= $turbo ) if ( $xFactor >= $turbo )
{ {
$panSpeed = $monitor['TurboPanSpeed']; $panSpeed = $monitor->TurboPanSpeed();
} }
else else
{ {
$xFactor = $xFactor/$turbo; $xFactor = $xFactor/$turbo;
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
} }
else else
{ {
$panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); $panSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$xFactor)));
} }
$ctrlCommand .= " --panspeed=".$panSpeed; $ctrlCommand .= " --panspeed=".$panSpeed;
} }
if ( $monitor['HasTiltSpeed'] && $yFactor ) if ( $monitor->HasTiltSpeed() && $yFactor )
{ {
if ( $monitor['HasTurboTilt'] ) if ( $monitor->HasTurboTilt() )
{ {
if ( $yFactor >= $turbo ) if ( $yFactor >= $turbo )
{ {
$tiltSpeed = $monitor['TurboTiltSpeed']; $tiltSpeed = $monitor->TurboTiltSpeed();
} }
else else
{ {
$yFactor = $yFactor/$turbo; $yFactor = $yFactor/$turbo;
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
} }
else else
{ {
$tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); $tiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$yFactor)));
} }
$ctrlCommand .= " --tiltspeed=".$tiltSpeed; $ctrlCommand .= " --tiltspeed=".$tiltSpeed;
} }
@ -900,22 +900,22 @@ function buildControlCommand( $monitor )
{ {
if ( preg_match( '/(Left|Right)$/', $dirn ) ) if ( preg_match( '/(Left|Right)$/', $dirn ) )
{ {
$panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); $panStep = intval(round($monitor->MinPanStep()+(($monitor->MaxPanStep()-$monitor->MinPanStep())*$xFactor)));
$ctrlCommand .= " --panstep=".$panStep; $ctrlCommand .= " --panstep=".$panStep;
} }
if ( preg_match( '/^(Up|Down)/', $dirn ) ) if ( preg_match( '/^(Up|Down)/', $dirn ) )
{ {
$tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); $tiltStep = intval(round($monitor->MinTiltStep()+(($monitor->MaxTiltStep()-$monitor->MinTiltStep())*$yFactor)));
$ctrlCommand .= " --tiltstep=".$tiltStep; $ctrlCommand .= " --tiltstep=".$tiltStep;
} }
break; break;
} }
case 'Con' : case 'Con' :
{ {
if ( $monitor['AutoStopTimeout'] ) if ( $monitor->AutoStopTimeout() )
{ {
$slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); $slowPanSpeed = intval(round($monitor->MinPanSpeed()+(($monitor->MaxPanSpeed()-$monitor->MinPanSpeed())*$slow)));
$slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); $slowTiltSpeed = intval(round($monitor->MinTiltSpeed()+(($monitor->MaxTiltSpeed()-$monitor->MinTiltSpeed())*$slow)));
if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) )
{ {
$ctrlCommand .= " --autostop"; $ctrlCommand .= " --autostop";
@ -943,12 +943,12 @@ function buildControlCommand( $monitor )
if ( canEdit( 'Control' ) ) { if ( canEdit( 'Control' ) ) {
$preset = validInt($_REQUEST['preset']); $preset = validInt($_REQUEST['preset']);
$newLabel = validJsStr($_REQUEST['newLabel']); $newLabel = validJsStr($_REQUEST['newLabel']);
$row = dbFetchOne( 'SELECT * FROM ControlPresets WHERE MonitorId = ? AND Preset = ?', NULL, array( $monitor['Id'], $preset ) ); $row = dbFetchOne( 'SELECT * FROM ControlPresets WHERE MonitorId = ? AND Preset = ?', NULL, array( $monitor->Id(), $preset ) );
if ( $newLabel != $row['Label'] ) { if ( $newLabel != $row['Label'] ) {
if ( $newLabel ) { if ( $newLabel ) {
dbQuery( 'REPLACE INTO ControlPresets ( MonitorId, Preset, Label ) VALUES ( ?, ?, ? )', array( $monitor['Id'], $preset, $newLabel ) ); dbQuery( 'REPLACE INTO ControlPresets ( MonitorId, Preset, Label ) VALUES ( ?, ?, ? )', array( $monitor->Id(), $preset, $newLabel ) );
} else { } else {
dbQuery( 'DELETE FROM ControlPresets WHERE MonitorId = ? AND Preset = ?', array( $monitor['Id'], $preset ) ); dbQuery( 'DELETE FROM ControlPresets WHERE MonitorId = ? AND Preset = ?', array( $monitor->Id(), $preset ) );
} }
} }
$ctrlCommand .= " --preset=".$preset; $ctrlCommand .= " --preset=".$preset;

View File

@ -94,6 +94,30 @@ function noCacheHeaders()
header("Pragma: no-cache"); // HTTP/1.0 header("Pragma: no-cache"); // HTTP/1.0
} }
function CORSHeaders() {
if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) {
# The following is left for future reference/use.
$valid = false;
$servers = dbFetchAll( 'SELECT * FROM Servers' );
if ( sizeof($servers) <= 1 ) {
# Only need CORSHeaders in the event that there are multiple servers in use.
return;
}
foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) {
$Server = new Server( $row );
if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) {
$valid = true;
header("Access-Control-Allow-Origin: " . $Server->Url() );
header("Access-Control-Allow-Headers: x-requested-with,x-request");
}
}
if ( ! $valid ) {
Warning( $_SERVER['HTTP_ORIGIN'] . " is not found in servers list." );
}
}
}
function getAuthUser( $auth ) function getAuthUser( $auth )
{ {
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) ) if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) )

View File

@ -48,6 +48,7 @@ if ( false )
require_once( 'includes/config.php' ); require_once( 'includes/config.php' );
require_once( 'includes/logger.php' ); require_once( 'includes/logger.php' );
require_once( 'includes/Server.php' );
if ( isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' ) if ( isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' )
{ {
@ -136,6 +137,9 @@ else
require_once( 'includes/lang.php' ); require_once( 'includes/lang.php' );
require_once( 'includes/functions.php' ); require_once( 'includes/functions.php' );
# Add Cross domain access headers
CORSHeaders();
// Check for valid content dirs // Check for valid content dirs
if ( !is_writable(ZM_DIR_EVENTS) || !is_writable(ZM_DIR_IMAGES) ) if ( !is_writable(ZM_DIR_EVENTS) || !is_writable(ZM_DIR_IMAGES) )
{ {

View File

@ -87,6 +87,7 @@ $SLANG = array(
'Actual' => 'Actual', 'Actual' => 'Actual',
'AddNewControl' => 'Add New Control', 'AddNewControl' => 'Add New Control',
'AddNewMonitor' => 'Add New Monitor', 'AddNewMonitor' => 'Add New Monitor',
'AddNewServer' => 'Add New Server',
'AddNewUser' => 'Add New User', 'AddNewUser' => 'Add New User',
'AddNewZone' => 'Add New Zone', 'AddNewZone' => 'Add New Zone',
'Alarm' => 'Alarm', 'Alarm' => 'Alarm',
@ -124,6 +125,8 @@ $SLANG = array(
'AttrMaxScore' => 'Max. Score', 'AttrMaxScore' => 'Max. Score',
'AttrMonitorId' => 'Monitor Id', 'AttrMonitorId' => 'Monitor Id',
'AttrMonitorName' => 'Monitor Name', 'AttrMonitorName' => 'Monitor Name',
'AttrServerId' => 'Server Id',
'AttrServerName' => 'Server Name',
'AttrName' => 'Name', 'AttrName' => 'Name',
'AttrNotes' => 'Notes', 'AttrNotes' => 'Notes',
'AttrSystemLoad' => 'System Load', 'AttrSystemLoad' => 'System Load',
@ -383,6 +386,7 @@ $SLANG = array(
'HighBW' => 'High&nbsp;B/W', 'HighBW' => 'High&nbsp;B/W',
'High' => 'High', 'High' => 'High',
'Home' => 'Home', 'Home' => 'Home',
'Hostname' => 'Hostname',
'Hour' => 'Hour', 'Hour' => 'Hour',
'Hue' => 'Hue', 'Hue' => 'Hue',
'Id' => 'Id', 'Id' => 'Id',

View File

@ -21,8 +21,6 @@
* Primary look and feel styles * Primary look and feel styles
*/ */
@import url("https://fonts.googleapis.com/css?family=Open+Sans:200,200italic,300,300italic,400,400italic,600,600italic,700");
body { body {
font-family: "Open Sans", Verdana, Arial, Helvetica, sans-serif; font-family: "Open Sans", Verdana, Arial, Helvetica, sans-serif;
font-size: 16px; font-size: 16px;

View File

@ -30,13 +30,13 @@ function getControlCommands( $monitor )
$cmds['PresetGoto'] = "presetGoto"; $cmds['PresetGoto'] = "presetGoto";
$cmds['PresetHome'] = "presetHome"; $cmds['PresetHome'] = "presetHome";
if ( !empty($monitor['CanZoom']) ) if ( !empty($monitor->CanZoom) )
{ {
if ( $monitor['CanZoomCon'] ) if ( $monitor->CanZoomCon() )
$cmds['ZoomRoot'] = "zoomCon"; $cmds['ZoomRoot'] = "zoomCon";
elseif ( $monitor['CanZoomRel'] ) elseif ( $monitor->CanZoomRel() )
$cmds['ZoomRoot'] = "zoomRel"; $cmds['ZoomRoot'] = "zoomRel";
elseif ( $monitor['CanZoomAbs'] ) elseif ( $monitor->CanZoomAbs() )
$cmds['ZoomRoot'] = "zoomAbs"; $cmds['ZoomRoot'] = "zoomAbs";
$cmds['ZoomTele'] = $cmds['ZoomRoot']."Tele"; $cmds['ZoomTele'] = $cmds['ZoomRoot']."Tele";
$cmds['ZoomWide'] = $cmds['ZoomRoot']."Wide"; $cmds['ZoomWide'] = $cmds['ZoomRoot']."Wide";
@ -45,13 +45,13 @@ function getControlCommands( $monitor )
$cmds['ZoomMan'] = "zoomMan"; $cmds['ZoomMan'] = "zoomMan";
} }
if ( !empty($monitor['CanFocus']) ) if ( !empty($monitor->CanFocus) )
{ {
if ( $monitor['CanFocusCon'] ) if ( $monitor->CanFocusCon() )
$cmds['FocusRoot'] = "focusCon"; $cmds['FocusRoot'] = "focusCon";
elseif ( $monitor['CanFocusRel'] ) elseif ( $monitor->CanFocusRel() )
$cmds['FocusRoot'] = "focusRel"; $cmds['FocusRoot'] = "focusRel";
elseif ( $monitor['CanFocusAbs'] ) elseif ( $monitor->CanFocusAbs() )
$cmds['FocusRoot'] = "focusAbs"; $cmds['FocusRoot'] = "focusAbs";
$cmds['FocusFar'] = $cmds['FocusRoot']."Far"; $cmds['FocusFar'] = $cmds['FocusRoot']."Far";
$cmds['FocusNear'] = $cmds['FocusRoot']."Near"; $cmds['FocusNear'] = $cmds['FocusRoot']."Near";
@ -60,13 +60,13 @@ function getControlCommands( $monitor )
$cmds['FocusMan'] = "focusMan"; $cmds['FocusMan'] = "focusMan";
} }
if ( !empty($monitor['CanIris']) ) if ( !empty($monitor->CanIris) )
{ {
if ( $monitor['CanIrisCon'] ) if ( $monitor->CanIrisCon() )
$cmds['IrisRoot'] = "irisCon"; $cmds['IrisRoot'] = "irisCon";
elseif ( $monitor['CanIrisRel'] ) elseif ( $monitor->CanIrisRel() )
$cmds['IrisRoot'] = "irisRel"; $cmds['IrisRoot'] = "irisRel";
elseif ( $monitor['CanIrisAbs'] ) elseif ( $monitor->CanIrisAbs() )
$cmds['IrisRoot'] = "irisAbs"; $cmds['IrisRoot'] = "irisAbs";
$cmds['IrisOpen'] = $cmds['IrisRoot']."Open"; $cmds['IrisOpen'] = $cmds['IrisRoot']."Open";
$cmds['IrisClose'] = $cmds['IrisRoot']."Close"; $cmds['IrisClose'] = $cmds['IrisRoot']."Close";
@ -75,13 +75,13 @@ function getControlCommands( $monitor )
$cmds['IrisMan'] = "irisMan"; $cmds['IrisMan'] = "irisMan";
} }
if ( !empty($monitor['CanWhite']) ) if ( !empty($monitor->CanWhite) )
{ {
if ( $monitor['CanWhiteCon'] ) if ( $monitor->CanWhiteCon() )
$cmds['WhiteRoot'] = "whiteCon"; $cmds['WhiteRoot'] = "whiteCon";
elseif ( $monitor['CanWhiteRel'] ) elseif ( $monitor->CanWhiteRel() )
$cmds['WhiteRoot'] = "whiteRel"; $cmds['WhiteRoot'] = "whiteRel";
elseif ( $monitor['CanWhiteAbs'] ) elseif ( $monitor->CanWhiteAbs() )
$cmds['WhiteRoot'] = "whiteAbs"; $cmds['WhiteRoot'] = "whiteAbs";
$cmds['WhiteIn'] = $cmds['WhiteRoot']."In"; $cmds['WhiteIn'] = $cmds['WhiteRoot']."In";
$cmds['WhiteOut'] = $cmds['WhiteRoot']."Out"; $cmds['WhiteOut'] = $cmds['WhiteRoot']."Out";
@ -89,13 +89,13 @@ function getControlCommands( $monitor )
$cmds['WhiteMan'] = "whiteMan"; $cmds['WhiteMan'] = "whiteMan";
} }
if ( !empty($monitor['CanGain']) ) if ( !empty($monitor->CanGain) )
{ {
if ( $monitor['CanGainCon'] ) if ( $monitor->CanGainCon() )
$cmds['GainRoot'] = "gainCon"; $cmds['GainRoot'] = "gainCon";
elseif ( $monitor['CanGainRel'] ) elseif ( $monitor->CanGainRel() )
$cmds['GainRoot'] = "gainRel"; $cmds['GainRoot'] = "gainRel";
elseif ( $monitor['CanGainAbs'] ) elseif ( $monitor->CanGainAbs() )
$cmds['GainRoot'] = "gainAbs"; $cmds['GainRoot'] = "gainAbs";
$cmds['GainUp'] = $cmds['GainRoot']."Up"; $cmds['GainUp'] = $cmds['GainRoot']."Up";
$cmds['GainDown'] = $cmds['GainRoot']."Down"; $cmds['GainDown'] = $cmds['GainRoot']."Down";
@ -103,19 +103,19 @@ function getControlCommands( $monitor )
$cmds['GainMan'] = "gainMan"; $cmds['GainMan'] = "gainMan";
} }
if ( !empty($monitor['CanMove']) ) if ( !empty($monitor->CanMove) )
{ {
if ( $monitor['CanMoveCon'] ) if ( $monitor->CanMoveCon() )
{ {
$cmds['MoveRoot'] = "moveCon"; $cmds['MoveRoot'] = "moveCon";
$cmds['Center'] = "moveStop"; $cmds['Center'] = "moveStop";
} }
elseif ( $monitor['CanMoveRel'] ) elseif ( $monitor->CanMoveRel() )
{ {
$cmds['MoveRoot'] = "moveRel"; $cmds['MoveRoot'] = "moveRel";
$cmds['Center'] = $cmds['PresetHome']; $cmds['Center'] = $cmds['PresetHome'];
} }
elseif ( $monitor['CanMoveAbs'] ) elseif ( $monitor->CanMoveAbs() )
{ {
$cmds['MoveRoot'] = "moveAbs"; $cmds['MoveRoot'] = "moveAbs";
$cmds['Center'] = $cmds['PresetHome']; $cmds['Center'] = $cmds['PresetHome'];
@ -142,11 +142,11 @@ function controlFocus( $monitor, $cmds )
<div class="arrowControl focusControls"> <div class="arrowControl focusControls">
<div class="arrowLabel"><?php echo translate('Near') ?></div> <div class="arrowLabel"><?php echo translate('Near') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['FocusNear'] ?>',event,0,-1)"></div> <div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['FocusNear'] ?>',event,0,-1)"></div>
<div class="arrowCenter"<?php if ( $monitor['CanFocusCon'] ) { ?> onclick="controlCmd('<?php echo $cmds['FocusStop'] ?>')"<?php } ?>><?php echo translate('Focus') ?></div> <div class="arrowCenter"<?php if ( $monitor->CanFocusCon() ) { ?> onclick="controlCmd('<?php echo $cmds['FocusStop'] ?>')"<?php } ?>><?php echo translate('Focus') ?></div>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['FocusFar'] ?>',event,0,1)"></div> <div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['FocusFar'] ?>',event,0,1)"></div>
<div class="arrowLabel"><?php echo translate('Far') ?></div> <div class="arrowLabel"><?php echo translate('Far') ?></div>
<?php <?php
if ( $monitor['CanAutoFocus'] ) if ( $monitor->CanAutoFocus() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['FocusAuto'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['FocusAuto'] ?>')"/>
@ -168,11 +168,11 @@ function controlZoom( $monitor, $cmds )
<div class="arrowControl zoomControls"> <div class="arrowControl zoomControls">
<div class="arrowLabel"><?php echo translate('Tele') ?></div> <div class="arrowLabel"><?php echo translate('Tele') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['ZoomTele'] ?>',event,0,-1)"></div> <div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['ZoomTele'] ?>',event,0,-1)"></div>
<div class="arrowCenter"<?php if ( $monitor['CanZoomCon'] ) { ?> onclick="controlCmd('<?php echo $cmds['ZoomStop'] ?>')"<?php } ?>><?php echo translate('Zoom') ?></div> <div class="arrowCenter"<?php if ( $monitor->CanZoomCon() ) { ?> onclick="controlCmd('<?php echo $cmds['ZoomStop'] ?>')"<?php } ?>><?php echo translate('Zoom') ?></div>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['ZoomWide'] ?>',event,0,1)"></div> <div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['ZoomWide'] ?>',event,0,1)"></div>
<div class="arrowLabel"><?php echo translate('Wide') ?></div> <div class="arrowLabel"><?php echo translate('Wide') ?></div>
<?php <?php
if ( $monitor['CanAutoZoom'] ) if ( $monitor->CanAutoZoom() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['ZoomAuto'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['ZoomAuto'] ?>')"/>
@ -193,11 +193,11 @@ function controlIris( $monitor, $cmds )
<div class="arrowControl irisControls"> <div class="arrowControl irisControls">
<div class="arrowLabel"><?php echo translate('Open') ?></div> <div class="arrowLabel"><?php echo translate('Open') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['IrisOpen'] ?>',event,0,-1)"></div> <div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['IrisOpen'] ?>',event,0,-1)"></div>
<div class="arrowCenter"<?php if ( $monitor['CanIrisCon'] ) { ?> onclick="controlCmd('<?php echo $cmds['IrisStop'] ?>')"<?php } ?>><?php echo translate('Iris') ?></div> <div class="arrowCenter"<?php if ( $monitor->CanIrisCon() ) { ?> onclick="controlCmd('<?php echo $cmds['IrisStop'] ?>')"<?php } ?>><?php echo translate('Iris') ?></div>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['IrisClose'] ?>',event,0,1)"></div> <div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['IrisClose'] ?>',event,0,1)"></div>
<div class="arrowLabel"><?php echo translate('Close') ?></div> <div class="arrowLabel"><?php echo translate('Close') ?></div>
<?php <?php
if ( $monitor['CanAutoIris'] ) if ( $monitor->CanAutoIris() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['IrisAuto'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['IrisAuto'] ?>')"/>
@ -219,11 +219,11 @@ function controlWhite( $monitor, $cmds )
<div class="arrowControl whiteControls"> <div class="arrowControl whiteControls">
<div class="arrowLabel"><?php echo translate('In') ?></div> <div class="arrowLabel"><?php echo translate('In') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['WhiteIn'] ?>',event,0,-1)"></div> <div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['WhiteIn'] ?>',event,0,-1)"></div>
<div class="arrowCenter"<?php if ( $monitor['CanWhiteCon'] ) { ?> onclick="controlCmd('<?php echo $cmds['WhiteStop'] ?>')"<?php } ?>><?php echo translate('White') ?></div> <div class="arrowCenter"<?php if ( $monitor->CanWhiteCon() ) { ?> onclick="controlCmd('<?php echo $cmds['WhiteStop'] ?>')"<?php } ?>><?php echo translate('White') ?></div>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['WhiteOut'] ?>',event,0,1)"></div> <div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['WhiteOut'] ?>',event,0,1)"></div>
<div class="arrowLabel"><?php echo translate('Out') ?></div> <div class="arrowLabel"><?php echo translate('Out') ?></div>
<?php <?php
if ( $monitor['CanAutoWhite'] ) if ( $monitor->CanAutoWhite() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['WhiteAuto'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['WhiteAuto'] ?>')"/>
@ -246,9 +246,9 @@ function controlPanTilt( $monitor, $cmds )
<div class="pantilLabel"><?php echo translate('PanTilt') ?></div> <div class="pantilLabel"><?php echo translate('PanTilt') ?></div>
<div class="pantiltButtons"> <div class="pantiltButtons">
<?php <?php
$hasPan = $monitor['CanPan']; $hasPan = $monitor->CanPan;
$hasTilt = $monitor['CanTilt']; $hasTilt = $monitor->CanTilt;
$hasDiag = $hasPan && $hasTilt && $monitor['CanMoveDiag']; $hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag;
?> ?>
<div class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></div> <div class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></div>
<div class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></div> <div class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></div>
@ -271,14 +271,14 @@ function controlPresets( $monitor, $cmds )
define( "MAX_PRESETS", "12" ); define( "MAX_PRESETS", "12" );
$sql = "select * from ControlPresets where MonitorId = '".$monitor['Id']."'"; $sql = 'select * from ControlPresets where MonitorId = ?';
$labels = array(); $labels = array();
foreach( dbFetchAll( $sql ) as $row ) foreach( dbFetchAll( $sql, NULL, array( $monitor->Id() ) ) as $row )
{ {
$labels[$row['Preset']] = $row['Label']; $labels[$row['Preset']] = $row['Label'];
} }
$presetBreak = (int)(($monitor['NumPresets']+1)/((int)(($monitor['NumPresets']-1)/MAX_PRESETS)+1)); $presetBreak = (int)(($monitor->NumPresets+1)/((int)(($monitor->NumPresets-1)/MAX_PRESETS)+1));
ob_start(); ob_start();
?> ?>
@ -286,7 +286,7 @@ function controlPresets( $monitor, $cmds )
<!--<div><?php echo translate('Presets') ?></div>--> <!--<div><?php echo translate('Presets') ?></div>-->
<div> <div>
<?php <?php
for ( $i = 1; $i <= $monitor['NumPresets']; $i++ ) for ( $i = 1; $i <= $monitor->NumPresets; $i++ )
{ {
?><input type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?$labels[$i]:"" ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/><?php ?><input type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?$labels[$i]:"" ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/><?php
if ( $i && (($i%$presetBreak) == 0) ) if ( $i && (($i%$presetBreak) == 0) )
@ -298,16 +298,16 @@ function controlPresets( $monitor, $cmds )
</div> </div>
<div> <div>
<?php <?php
if ( $monitor['HasHomePreset'] ) if ( $monitor->HasHomePreset() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Home') ?>" onclick="controlCmd('<?php echo $cmds['PresetHome'] ?>');"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Home') ?>" onclick="controlCmd('<?php echo $cmds['PresetHome'] ?>');"/>
<?php <?php
} }
if ( canEdit( 'Monitors') && $monitor['CanSetPresets'] ) if ( canEdit( 'Monitors') && $monitor->CanSetPresets() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Set') ?>" onclick="createPopup( '?view=controlpreset&amp;mid=<?php echo $monitor['Id'] ?>', 'zmPreset', 'preset' );"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Set') ?>" onclick="createPopup( '?view=controlpreset&amp;mid=<?php echo $monitor->Id() ?>', 'zmPreset', 'preset' );"/>
<?php <?php
} }
?> ?>
@ -327,19 +327,19 @@ function controlPower( $monitor, $cmds )
<div class="powerLabel"><?php echo translate('Control') ?></div> <div class="powerLabel"><?php echo translate('Control') ?></div>
<div> <div>
<?php <?php
if ( $monitor['CanWake'] ) if ( $monitor->CanWake() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Wake') ?>" onclick="controlCmd('<?php echo $cmds['Wake'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Wake') ?>" onclick="controlCmd('<?php echo $cmds['Wake'] ?>')"/>
<?php <?php
} }
if ( $monitor['CanSleep'] ) if ( $monitor->CanSleep() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Sleep') ?>" onclick="controlCmd('<?php echo $cmds['Sleep'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Sleep') ?>" onclick="controlCmd('<?php echo $cmds['Sleep'] ?>')"/>
<?php <?php
} }
if ( $monitor['CanReset'] ) if ( $monitor->CanReset() )
{ {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Reset') ?>" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"/> <input type="button" class="ptzTextBtn" value="<?php echo translate('Reset') ?>" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"/>
@ -359,22 +359,22 @@ function ptzControls( $monitor )
?> ?>
<div class="controlsPanel"> <div class="controlsPanel">
<?php <?php
if ( $monitor['CanFocus'] ) if ( $monitor->CanFocus() )
echo controlFocus( $monitor, $cmds ); echo controlFocus( $monitor, $cmds );
if ( $monitor['CanZoom'] ) if ( $monitor->CanZoom() )
echo controlZoom( $monitor, $cmds ); echo controlZoom( $monitor, $cmds );
if ( $monitor['CanIris'] ) if ( $monitor->CanIris() )
echo controlIris( $monitor, $cmds ); echo controlIris( $monitor, $cmds );
if ( $monitor['CanWhite'] ) if ( $monitor->CanWhite() )
echo controlWhite( $monitor, $cmds ); echo controlWhite( $monitor, $cmds );
if ( $monitor['CanMove'] || ( $monitor['CanWake'] || $monitor['CanSleep'] || $monitor['CanReset'] ) ) if ( $monitor->CanMove() || ( $monitor->CanWake() || $monitor->CanSleep() || $monitor->CanReset() ) )
{ {
?> ?>
<div class="pantiltPanel"> <div class="pantiltPanel">
<?php <?php
if ( $monitor['CanMove'] ) if ( $monitor->CanMove() )
echo controlPanTilt( $monitor, $cmds ); echo controlPanTilt( $monitor, $cmds );
if ( $monitor['CanWake'] || $monitor['CanSleep'] || $monitor['CanReset'] ) if ( $monitor->CanWake() || $monitor->CanSleep() || $monitor->CanReset() )
echo controlPower( $monitor, $cmds ); echo controlPower( $monitor, $cmds );
?> ?>
</div> </div>
@ -383,7 +383,7 @@ function ptzControls( $monitor )
?> ?>
</div> </div>
<?php <?php
if ( $monitor['HasPresets'] ) if ( $monitor->HasPresets() )
echo controlPresets( $monitor, $cmds ); echo controlPresets( $monitor, $cmds );
return( ob_get_clean() ); return( ob_get_clean() );
} }

View File

@ -47,7 +47,7 @@ var popupSizes = {
'image': { 'addWidth': 48, 'addHeight': 80 }, 'image': { 'addWidth': 48, 'addHeight': 80 },
'log': { 'width': 1080, 'height': 720 }, 'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 }, 'login': { 'width': 720, 'height': 480 },
'logout': { 'width': 260, 'height': 100 }, 'logout': { 'width': 260, 'height': 150 },
'monitor': { 'width': 525, 'height': 700 }, 'monitor': { 'width': 525, 'height': 700 },
'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorpreset':{ 'width': 440, 'height': 200 },
'monitorprobe': { 'width': 500, 'height': 240 }, 'monitorprobe': { 'width': 500, 'height': 240 },

View File

@ -47,8 +47,8 @@ var popupSizes = {
'image': { 'addWidth': 48, 'addHeight': 80 }, 'image': { 'addWidth': 48, 'addHeight': 80 },
'log': { 'width': 1080, 'height': 720 }, 'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 }, 'login': { 'width': 720, 'height': 480 },
'logout': { 'width': 260, 'height': 100 }, 'logout': { 'width': 260, 'height': 150 },
'monitor': { 'width': 525, 'height': 700 }, 'monitor': { 'width': 550, 'height': 700 },
'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorpreset':{ 'width': 440, 'height': 200 },
'monitorprobe': { 'width': 500, 'height': 240 }, 'monitorprobe': { 'width': 500, 'height': 240 },
'monitorselect':{ 'width': 160, 'height': 200 }, 'monitorselect':{ 'width': 160, 'height': 200 },

View File

@ -18,6 +18,9 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
require_once('includes/Server.php');
$servers = Server::find_all();
$eventCounts = array( $eventCounts = array(
array( array(
"title" => translate('Events'), "title" => translate('Events'),
@ -235,6 +238,9 @@ else
<tr> <tr>
<th class="colName"><?php echo translate('Name') ?></th> <th class="colName"><?php echo translate('Name') ?></th>
<th class="colFunction"><?php echo translate('Function') ?></th> <th class="colFunction"><?php echo translate('Function') ?></th>
<?php if ( count($servers) ) { ?>
<th class="colServer"><?php echo translate('Server') ?></th>
<?php } ?>
<th class="colSource"><?php echo translate('Source') ?></th> <th class="colSource"><?php echo translate('Source') ?></th>
<?php <?php
for ( $i = 0; $i < count($eventCounts); $i++ ) for ( $i = 0; $i < count($eventCounts); $i++ )
@ -258,7 +264,7 @@ if ( canEdit('Monitors') )
</thead> </thead>
<tfoot> <tfoot>
<tr> <tr>
<td class="colLeftButtons" colspan="3"> <td class="colLeftButtons" colspan="<?php echo count($servers) ? 4 : 3 ?>">
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/> <input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
<?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?>
<?php echo makePopupButton( '?view=filter&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?> <?php echo makePopupButton( '?view=filter&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
@ -305,6 +311,12 @@ foreach( $displayMonitors as $monitor )
?> ?>
<td class="colName"><?php echo makePopupLink( '?view=watch&amp;mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView( 'Stream' ) ) ?></td> <td class="colName"><?php echo makePopupLink( '?view=watch&amp;mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView( 'Stream' ) ) ?></td>
<td class="colFunction"><?php echo makePopupLink( '?view=function&amp;mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?></td> <td class="colFunction"><?php echo makePopupLink( '?view=function&amp;mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?></td>
<?php if ( count($servers) ) { ?>
<td class="colServer"><?php
$Server = new Server( $monitor['ServerId'] );
echo $Server->Name();
?></td>
<?php } ?>
<?php if ( $monitor['Type'] == "Local" ) { ?> <?php if ( $monitor['Type'] == "Local" ) { ?>
<td class="colSource"><?php echo makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$monitor['Device'].' ('.$monitor['Channel'].')</span>', canEdit( 'Monitors' ) ) ?></td> <td class="colSource"><?php echo makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$monitor['Device'].' ('.$monitor['Channel'].')</span>', canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "Remote" ) { ?> <?php } elseif ( $monitor['Type'] == "Remote" ) { ?>

View File

@ -84,6 +84,8 @@ $attrTypes = array(
'DiskPercent' => translate('AttrDiskPercent'), 'DiskPercent' => translate('AttrDiskPercent'),
'DiskBlocks' => translate('AttrDiskBlocks'), 'DiskBlocks' => translate('AttrDiskBlocks'),
'SystemLoad' => translate('AttrSystemLoad'), 'SystemLoad' => translate('AttrSystemLoad'),
'ServerId' => translate('AttrServerId'),
'ServerName' => translate('AttrServerName'),
); );
$opTypes = array( $opTypes = array(
'=' => translate('OpEq'), '=' => translate('OpEq'),

View File

@ -22,7 +22,7 @@ var logTimeout = maxSampleTime;
var firstLoad = true; var firstLoad = true;
var initialDisplayLimit = 200; var initialDisplayLimit = 200;
var sortReversed = false; var sortReversed = false;
var filterFields = [ 'Component', 'Pid', 'Level', 'File', 'Line']; var filterFields = [ 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line'];
var options = {}; var options = {};
function buildFetchParms( parms ) function buildFetchParms( parms )
@ -68,7 +68,7 @@ function logResponse( respObj )
maxLogTime = log.TimeKey; maxLogTime = log.TimeKey;
if ( !minLogTime || log.TimeKey < minLogTime ) if ( !minLogTime || log.TimeKey < minLogTime )
minLogTime = log.TimeKey; minLogTime = log.TimeKey;
var row = logTable.push( [ { content: log.DateTime, properties: { style: 'white-space: nowrap' }}, log.Component, log.Pid, log.Code, log.Message, log.File, log.Line ] ); var row = logTable.push( [ { content: log.DateTime, properties: { style: 'white-space: nowrap' }}, log.Component, log.Server, log.Pid, log.Code, log.Message, log.File, log.Line ] );
delete log.Message; delete log.Message;
row.tr.store( 'log', log ); row.tr.store( 'log', log );
if ( log.Level <= -3 ) if ( log.Level <= -3 )
@ -163,6 +163,12 @@ function filterLog()
function( field ) function( field )
{ {
var selector = $('filter['+field+']'); var selector = $('filter['+field+']');
if ( ! selector ) {
if ( window.console && window.console.log ) {
window.console.log("No selector found for " + field );
}
return;
}
var value = selector.get('value'); var value = selector.get('value');
if ( value ) if ( value )
filter[field] = value; filter[field] = value;
@ -244,6 +250,12 @@ function updateFilterSelectors()
function( values, key ) function( values, key )
{ {
var selector = $('filter['+key+']'); var selector = $('filter['+key+']');
if ( ! selector ) {
if ( window.console && window.console.log ) {
window.console.log("No selector found for " + key );
}
return;
}
selector.options.length = 1; selector.options.length = 1;
if ( key == 'Level' ) if ( key == 'Level' )
{ {
@ -253,6 +265,15 @@ function updateFilterSelectors()
selector.options[selector.options.length] = new Option( value, label ); selector.options[selector.options.length] = new Option( value, label );
} }
); );
}
else if ( key == 'ServerId' )
{
Object.each(values,
function( value, label )
{
selector.options[selector.options.length] = new Option( value, label );
}
);
} }
else else
{ {

View File

@ -31,7 +31,12 @@ var monitorData = new Array();
foreach ( $monitors as $monitor ) foreach ( $monitors as $monitor )
{ {
?> ?>
monitorData[monitorData.length] = { 'id': <?php echo $monitor['Id'] ?>, 'connKey': <?php echo $monitor['connKey'] ?>, 'width': <?php echo $monitor['Width'] ?>,'height':<?php echo $monitor['Height'] ?> }; monitorData[monitorData.length] = {
'id': <?php echo $monitor->Id() ?>,
'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->Width() ?>,
'height':<?php echo $monitor->Height() ?>
};
<?php <?php
} }
?> ?>

View File

@ -0,0 +1,14 @@
function validateForm( form, newServer )
{
var errors = new Array();
if ( !form.elements['newServer[Name]'].value )
{
errors[errors.length] = "You must supply a name";
}
if ( errors.length )
{
alert( errors.join( "\n" ) );
return( false );
}
return( true );
}

View File

@ -100,7 +100,7 @@ function setAlarmState( currentAlarmState )
} }
var streamCmdParms = "view=request&request=stream&connkey="+connKey; var streamCmdParms = "view=request&request=stream&connkey="+connKey;
var streamCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStreamCmdResponse } ); var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStreamCmdResponse } );
var streamCmdTimer = null; var streamCmdTimer = null;
var streamStatus; var streamStatus;
@ -348,7 +348,7 @@ function streamCmdQuery()
} }
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
var statusCmdReq = new Request.JSON( { url: thisUrl, method: 'post', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } );
var statusCmdTimer = null; var statusCmdTimer = null;
function getStatusCmdResponse( respObj, respText ) function getStatusCmdResponse( respObj, respText )
@ -377,7 +377,7 @@ function statusCmdQuery()
} }
var alarmCmdParms = "view=request&request=alarm&id="+monitorId; var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
var alarmCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getAlarmCmdResponse, onTimeout: streamCmdQuery } ); var alarmCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getAlarmCmdResponse, onTimeout: streamCmdQuery } );
var alarmCmdFirst = true; var alarmCmdFirst = true;
function getAlarmCmdResponse( respObj, respText ) function getAlarmCmdResponse( respObj, respText )

View File

@ -44,9 +44,11 @@ var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"eve
var connKey = '<?php echo $connkey ?>'; var connKey = '<?php echo $connkey ?>';
var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>; var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>;
var monitorId = <?php echo $monitor['Id'] ?>;
var monitorWidth = <?php echo $monitor['Width'] ?>; var monitorId = <?php echo $monitor->Id() ?>;
var monitorHeight = <?php echo $monitor['Height'] ?>; var monitorWidth = <?php echo $monitor->Width() ?>;
var monitorHeight = <?php echo $monitor->Height() ?>;
var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
var scale = <?php echo $scale ?>; var scale = <?php echo $scale ?>;
@ -61,11 +63,11 @@ var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
var canPlayPauseAudio = Browser.ie; var canPlayPauseAudio = Browser.ie;
<?php if ( $monitor['CanMoveMap'] ) { ?> <?php if ( $monitor->CanMoveMap() ) { ?>
var imageControlMode = "moveMap"; var imageControlMode = "moveMap";
<?php } elseif ( $monitor['CanMoveRel'] ) { ?> <?php } elseif ( $monitor->CanMoveRel() ) { ?>
var imageControlMode = "movePseudoMap"; var imageControlMode = "movePseudoMap";
<?php } elseif ( $monitor['CanMoveCon'] ) { ?> <?php } elseif ( $monitor->CanMoveCon() ) { ?>
var imageControlMode = "moveConMap"; var imageControlMode = "moveConMap";
<?php } else { ?> <?php } else { ?>
var imageControlMode = null; var imageControlMode = null;

View File

@ -54,6 +54,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
<div id="content"> <div id="content">
<div id="filters"><?php echo translate('FilterLog') ?> - <div id="filters"><?php echo translate('FilterLog') ?> -
<?php echo translate('Component') ?> <select id="filter[Component]" onchange="filterLog(this)"><option value="">-----</option></select> <?php echo translate('Component') ?> <select id="filter[Component]" onchange="filterLog(this)"><option value="">-----</option></select>
<?php echo translate('Server') ?> <select id="filter[ServerId]" onchange="filterLog(this)"><option value="">-----</option></select>
<?php echo translate('Pid') ?> <select id="filter[Pid]" onchange="filterLog(this)"><option value="">-----</option></select> <?php echo translate('Pid') ?> <select id="filter[Pid]" onchange="filterLog(this)"><option value="">-----</option></select>
<?php echo translate('Level') ?> <select id="filter[Level]" onchange="filterLog(this)"><option value="">---</option></select> <?php echo translate('Level') ?> <select id="filter[Level]" onchange="filterLog(this)"><option value="">---</option></select>
<?php echo translate('File') ?> <select id="filter[File]" onchange="filterLog(this)"><option value="">------</option></select> <?php echo translate('File') ?> <select id="filter[File]" onchange="filterLog(this)"><option value="">------</option></select>
@ -67,6 +68,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
<tr> <tr>
<th><?php echo translate('DateTime') ?></th> <th><?php echo translate('DateTime') ?></th>
<th class="table-th-nosort"><?php echo translate('Component') ?></th> <th class="table-th-nosort"><?php echo translate('Component') ?></th>
<th class="table-th-nosort"><?php echo translate('Server') ?></th>
<th class="table-th-nosort"><?php echo translate('Pid') ?></th> <th class="table-th-nosort"><?php echo translate('Pid') ?></th>
<th class="table-th-nosort"><?php echo translate('Level') ?></th> <th class="table-th-nosort"><?php echo translate('Level') ?></th>
<th class="table-th-nosort"><?php echo translate('Message') ?></th> <th class="table-th-nosort"><?php echo translate('Message') ?></th>

View File

@ -18,6 +18,8 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
require_once( 'includes/Server.php');
if ( !canView( 'Monitors' ) ) if ( !canView( 'Monitors' ) )
{ {
$view = "error"; $view = "error";
@ -41,6 +43,7 @@ if ( isset($_REQUEST['tab']) )
else else
$tab = "general"; $tab = "general";
$Server = null;
if ( defined( 'ZM_SERVER_ID' ) ) { if ( defined( 'ZM_SERVER_ID' ) ) {
$Server = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( ZM_SERVER_ID ) ); $Server = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( ZM_SERVER_ID ) );
} }
@ -672,8 +675,12 @@ switch ( $tab )
<tr><td><?php echo translate('Name') ?></td><td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($newMonitor['Name']) ?>" size="16"/></td></tr> <tr><td><?php echo translate('Name') ?></td><td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($newMonitor['Name']) ?>" size="16"/></td></tr>
<tr><td><?php echo translate('Server') ?></td><td> <tr><td><?php echo translate('Server') ?></td><td>
<?php <?php
$servers = dbFetchAssoc( 'SELECT Id,Name FROM Servers ORDER BY Name', 'Id', 'Name' ); $servers = array(''=>'None');
array_unshift( $servers, 'None' ); $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name');
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server' );
foreach ( $results as $row => $server_obj ) {
$servers[$server_obj->Id] = $server_obj->Name();
}
?> ?>
<?php echo buildSelect( "newMonitor[ServerId]", $servers ); ?> <?php echo buildSelect( "newMonitor[ServerId]", $servers ); ?>
</td></tr> </td></tr>

View File

@ -24,6 +24,8 @@ if ( !canView( 'Stream' ) )
return; return;
} }
require_once( 'includes/Monitor.php' );
$groupSql = ""; $groupSql = "";
if ( !empty($_REQUEST['group']) ) if ( !empty($_REQUEST['group']) )
{ {
@ -64,7 +66,7 @@ foreach( dbFetchAll( $sql ) as $row )
$row['scaleWidth'] = $scaleWidth; $row['scaleWidth'] = $scaleWidth;
$row['scaleHeight'] = $scaleHeight; $row['scaleHeight'] = $scaleHeight;
$row['connKey'] = generateConnKey(); $row['connKey'] = generateConnKey();
$monitors[] = $row; $monitors[] = new Monitor( $row );
} }
$focusWindow = true; $focusWindow = true;
@ -107,29 +109,29 @@ if ( $showControl )
<?php <?php
foreach ( $monitors as $monitor ) foreach ( $monitors as $monitor )
{ {
$connkey = $monitor['connKey']; // Minor hack $connkey = $monitor->connKey(); // Minor hack
if ( !isset( $scale ) ) if ( !isset( $scale ) )
$scale = reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); $scale = reScale( SCALE_BASE, $monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE );
?> ?>
<div id="monitorFrame<?php echo $monitor['index'] ?>" class="monitorFrame"> <div id="monitorFrame<?php echo $monitor->index() ?>" class="monitorFrame">
<div id="monitor<?php echo $monitor['index'] ?>" class="monitor idle"> <div id="monitor<?php echo $monitor->index() ?>" class="monitor idle">
<div id="imageFeed<?php echo $monitor['index'] ?>" class="imageFeed" onclick="createPopup( '?view=watch&amp;mid=<?php echo $monitor['Id'] ?>', 'zmWatch<?php echo $monitor['Id'] ?>', 'watch', <?php echo $monitor['scaleWidth'] ?>, <?php echo $monitor['scaleHeight'] ?> );"> <div id="imageFeed<?php echo $monitor->index() ?>" class="imageFeed" onclick="createPopup( '?view=watch&amp;mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo $monitor->scaleWidth() ?>, <?php echo $monitor->scaleHeight() ?> );">
<?php <?php
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT )
{ {
$streamSrc = getStreamSrc( array( "mode=mpeg", "monitor=".$monitor['Id'], "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=mpeg", "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) );
outputVideoStream( "liveStream".$monitor['Id'], $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), ZM_MPEG_LIVE_FORMAT ); outputVideoStream( "liveStream".$monitor->Id(), $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), ZM_MPEG_LIVE_FORMAT );
} }
else else
{ {
$streamSrc = getStreamSrc( array( "mode=jpeg", "monitor=".$monitor['Id'], "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=jpeg", "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS ) );
if ( canStreamNative() ) if ( canStreamNative() )
{ {
outputImageStream( "liveStream".$monitor['Id'], $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), validHtmlStr($monitor['Name']) ); outputImageStream( "liveStream".$monitor->Id(), $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), validHtmlStr($monitor->Name()) );
} }
else else
{ {
outputHelperStream( "liveStream".$monitor['Id'], $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ); outputHelperStream( "liveStream".$monitor->Id(), $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ) );
} }
} }
?> ?>
@ -138,7 +140,7 @@ else
if ( !ZM_WEB_COMPACT_MONTAGE ) if ( !ZM_WEB_COMPACT_MONTAGE )
{ {
?> ?>
<div id="monitorState<?php echo $monitor['index'] ?>" class="monitorState idle"><?php echo translate('State') ?>:&nbsp;<span id="stateValue<?php echo $monitor['index'] ?>"></span>&nbsp;-&nbsp;<span id="fpsValue<?php echo $monitor['index'] ?>"></span>&nbsp;fps</div> <div id="monitorState<?php echo $monitor->index() ?>" class="monitorState idle"><?php echo translate('State') ?>:&nbsp;<span id="stateValue<?php echo $monitor->index() ?>"></span>&nbsp;-&nbsp;<span id="fpsValue<?php echo $monitor->index() ?>"></span>&nbsp;fps</div>
<?php <?php
} }
?> ?>

View File

@ -221,13 +221,15 @@ elseif ( $tab == "users" )
<thead> <thead>
<tr> <tr>
<th class="colName"><?php echo translate('name') ?></th> <th class="colName"><?php echo translate('name') ?></th>
<th class="colHostname"><?php echo translate('Hostname') ?></th>
<th class="colMark"><?php echo translate('Mark') ?></th> <th class="colMark"><?php echo translate('Mark') ?></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { ?> <?php foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { ?>
<tr> <tr>
<td class="colName"><?php echo makePopupLink( '?view=server&amp;id='.$row['Id'], 'zmServer', 'server', validHtmlStr($row['Name']).($user['Name']==$row['Name']?"*":""), $canEdit ) ?></td> <td class="colName"><?php echo makePopupLink( '?view=server&amp;id='.$row['Id'], 'zmServer', 'server', validHtmlStr($row['Name']), $canEdit ) ?></td>
<td class="colHostname"><?php echo makePopupLink( '?view=server&amp;id='.$row['Id'], 'zmServer', 'server', validHtmlStr($row['Hostname']), $canEdit ) ?></td>
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $row['Id'] ?>" onclick="configureDeleteButton( this );"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td> <td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $row['Id'] ?>" onclick="configureDeleteButton( this );"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
</tr> </tr>
<?php } #end foreach Server ?> <?php } #end foreach Server ?>

View File

@ -32,6 +32,7 @@ if ( $_REQUEST['id'] ) {
} else { } else {
$newServer = array(); $newServer = array();
$newServer['Name'] = translate('NewServer'); $newServer['Name'] = translate('NewServer');
$newServer['Hostname'] = '';
} }
$focusWindow = true; $focusWindow = true;
@ -51,14 +52,19 @@ xhtmlHeaders(__FILE__, translate('Server')." - ".$newServer['Name'] );
<table id="contentTable" class="major" cellspacing="0"> <table id="contentTable" class="major" cellspacing="0">
<tbody> <tbody>
<tr> <tr>
<th scope="row"><?php echo translate('ServerName') ?></th> <th scope="row"><?php echo translate('Name') ?></th>
<td><input type="text" name="newServer[Name]" value="<?php echo $newServer['Name'] ?>"/></td> <td><input type="text" name="newServer[Name]" value="<?php echo $newServer['Name'] ?>"/></td>
</tr> </tr>
<tr>
<th scope="row"><?php echo translate('Hostname') ?></th>
<td><input type="text" name="newServer[Hostname]" value="<?php echo $newServer['Hostname'] ?>"/></td>
</tr>
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div id="contentButtons">
<input type="submit" name="action" value="<?php echo translate('Save') ?>"/> <input type="hidden" name="action" value="Save"/>
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/> <input type="submit" value="<?php echo translate('Save') ?>"/>
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow();"/>
</div> </div>
</form> </form>
</div> </div>

View File

@ -18,61 +18,67 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
require_once('includes/Monitor.php');
if ( !canView( 'Stream' ) ) if ( !canView( 'Stream' ) )
{ {
$view = "error"; $view = "error";
return; return;
} }
if ( ! visibleMonitor( $_REQUEST['mid'] ) ) {
// This is for input sanitation
$mid = intval( $_REQUEST['mid'] );
if ( ! visibleMonitor( $mid ) ) {
$view = "error"; $view = "error";
return; return;
} }
$sql = 'SELECT C.*, M.* FROM Monitors AS M LEFT JOIN Controls AS C ON (M.ControlId = C.Id ) WHERE M.Id = ?'; $sql = 'SELECT C.*, M.* FROM Monitors AS M LEFT JOIN Controls AS C ON (M.ControlId = C.Id ) WHERE M.Id = ?';
$monitor = dbFetchOne( $sql, NULL, array( $_REQUEST['mid'] ) ); $monitor = new Monitor( $mid );
#dbFetchOne( $sql, NULL, array( $_REQUEST['mid'] ) );
if ( isset($_REQUEST['showControls']) ) if ( isset($_REQUEST['showControls']) )
$showControls = validInt($_REQUEST['showControls']); $showControls = validInt($_REQUEST['showControls']);
else else
$showControls = (canView( 'Control' ) && ($monitor['DefaultView'] == 'Control')); $showControls = (canView( 'Control' ) && ($monitor->DefaultView() == 'Control'));
$showPtzControls = ( ZM_OPT_CONTROL && $monitor['Controllable'] && canView( 'Control' ) ); $showPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView( 'Control' ) );
if ( isset( $_REQUEST['scale'] ) ) if ( isset( $_REQUEST['scale'] ) )
$scale = validInt($_REQUEST['scale']); $scale = validInt($_REQUEST['scale']);
else else
$scale = reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); $scale = reScale( SCALE_BASE, $monitor->DefaultScale, ZM_WEB_DEFAULT_SCALE );
$connkey = generateConnKey(); $connkey = generateConnKey();
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT )
{ {
$streamMode = "mpeg"; $streamMode = "mpeg";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=".$streamMode, "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) );
} }
elseif ( canStream() ) elseif ( canStream() )
{ {
$streamMode = "jpeg"; $streamMode = "jpeg";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "buffer=".$monitor['StreamReplayBuffer'] ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=".$streamMode, "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "buffer=".$monitor->StreamReplayBuffer() ) );
} }
else else
{ {
$streamMode = "single"; $streamMode = "single";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=".$streamMode, "scale=".$scale ) );
Info( "The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser."); Info( "The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.");
} }
$showDvrControls = ( $streamMode == 'jpeg' && $monitor['StreamReplayBuffer'] != 0 ); $showDvrControls = ( $streamMode == 'jpeg' && $monitor->StreamReplayBuffer() != 0 );
noCacheHeaders(); noCacheHeaders();
xhtmlHeaders( __FILE__, $monitor['Name']." - ".translate('Feed') ); xhtmlHeaders( __FILE__, $monitor->Name()." - ".translate('Feed') );
?> ?>
<body> <body>
<div id="page"> <div id="page">
<div id="content"> <div id="content">
<div id="menuBar"> <div id="menuBar">
<div id="monitorName"><?php echo $monitor['Name'] ?></div> <div id="monitorName"><?php echo $monitor->Name() ?></div>
<div id="closeControl"><a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a></div> <div id="closeControl"><a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a></div>
<div id="menuControls"> <div id="menuControls">
<?php <?php
@ -93,10 +99,10 @@ if ( $showPtzControls )
} }
?> ?>
<?php <?php
if ( canView( 'Control' ) && $monitor['Type'] == "Local" ) if ( canView( 'Control' ) && $monitor->Type() == "Local" )
{ {
?> ?>
<div id="settingsControl"><?php echo makePopupLink( '?view=settings&amp;mid='.$monitor['Id'], 'zmSettings'.$monitor['Id'], 'settings', translate('Settings'), true, 'id="settingsLink"' ) ?></div> <div id="settingsControl"><?php echo makePopupLink( '?view=settings&amp;mid='.$monitor->Id(), 'zmSettings'.$monitor->Id(), 'settings', translate('Settings'), true, 'id="settingsLink"' ) ?></div>
<?php <?php
} }
?> ?>
@ -107,18 +113,18 @@ if ( canView( 'Control' ) && $monitor['Type'] == "Local" )
<?php <?php
if ( $streamMode == "mpeg" ) if ( $streamMode == "mpeg" )
{ {
outputVideoStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), ZM_MPEG_LIVE_FORMAT, $monitor['Name'] ); outputVideoStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
} }
elseif ( $streamMode == "jpeg" ) elseif ( $streamMode == "jpeg" )
{ {
if ( canStreamNative() ) if ( canStreamNative() )
outputImageStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), $monitor['Name'] ); outputImageStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
elseif ( canStreamApplet() ) elseif ( canStreamApplet() )
outputHelperStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), $monitor['Name'] ); outputHelperStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
} }
else else
{ {
outputImageStill( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), $monitor['Name'] ); outputImageStill( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
} }
?> ?>
</div> </div>